I have been trying to get my head around delegates in C#, but I just don't seem to get the point how to use them.
I have a program that should do the following with delegates:
Main.cs:
Create 1 server;
Create 3 clients;
Register clients to server;
Send message from server to all registered clients;
Unregister 1 client and send message from server to registered clients;
Send message from server to specific client.
Server.cs:
public delegate MsgSend(string message);
private MsgSend msgSend;
public void Register(MsgSend m);
public void Unregister(MsgSend m);
public void SendMessage(string message);
Clien.cs:
private string id;
public Client(string id); - explicit constructor;
public void ClientRegister(Server server);
public void ClientUnregister(Server server);
public void PrintMessage(string message);
How should I use the delegate int this situation...?
Any help with some explanations how and where things are happening in this program will be in great use for me.
Thanks in advance.
Here is the code:
Server:
public delegate string MsgSend(string message);
class Server
{
private MsgSend msgSend;
public void Register(MsgSend m)
{ // Is this the right way to use the delegate as multicast delegate
// to register the client and say it is registered or
// I should do extremely different thing here?
msgSend += new MsgSend(m);
m("xx");
}
public void Unregister(MsgSend m)
{ // Is this the right way to use the delegate as multicast delegate
// to register the client and say it is registered or
// I should do extremely different thing here?
msgSend += new MsgSend(m);
m("yy");
}
public void SendMessage(string message)
{
Console.WriteLine(message + this.msgSend);
}
}
Client:
class Client
{
public string id;
public Client(string id)
{
this.id = id;
}
public void ClientRegister(Server server)
{
server.Register(...); // What should I pass as parameter here and why...
}
public void ClientUnregister(Server server)
{
server.Unregister(...); // What should I pass as parameter here and why...
}
public void PrintMessage(string message)
{
Console.WriteLine(id + " recieved: " + message);
}
}
Main:
class Program
{
static void Main(string[] args)
{ // Is this enough in the main program so the program to work?
Server svr = new Server();
Client cl1 = new Client("123");
Client cl2 = new Client("456");
Client cl3 = new Client("789");
cl1.ClientRegister(svr);
cl2.ClientRegister(svr);
cl3.ClientRegister(svr);
svr.SendMessage("message from server");
}
}
Here is full working code:
Main
using System;
static partial class Program
{
static void Main()
{
Server svr = new Server();
Client cl1 = new Client("123");
Client cl2 = new Client("456");
Client cl3 = new Client("789");
// Register
cl1.ClientRegister(svr);
cl2.ClientRegister(svr);
cl3.ClientRegister(svr);
svr.SendMessage("message from server");
// Unregister
cl1.ClientUnregister(svr);
cl2.ClientUnregister(svr);
cl3.ClientUnregister(svr);
// Try send string when you unregistered all clients
svr.SendMessage("message from server again");
Console.ReadLine();
}
}
Server
class Server
{
public delegate void MsgSend(string message);
private MsgSend msgSend;
public void Register(MsgSend m)
{
msgSend += m;
m("Registered");
}
public void Unregister(MsgSend m)
{
msgSend -= m; // <--- Change += to -=
m("Unregistered");
}
public void SendMessage(string message)
{
//You have to check if msgSend is null:
if (msgSend != null) this.msgSend(message);
else Console.WriteLine("DONT HAVE ANY CLIENT!");
}
}
Client
class Client
{
public string id;
public Client(string id)
{
this.id = id;
}
public void ClientRegister(Server server)
{
server.Register(PrintMessage);
}
public void ClientUnregister(Server server)
{
server.Unregister(PrintMessage);
}
public void PrintMessage(string message)
{
Console.WriteLine("Client " + id + " recieved: " + message);
}
}
When run Main() you will receive:
Client 123 recieved: Registered
Client 456 recieved: Registered
Client 789 recieved: Registered
Client 123 recieved: message from server
Client 456 recieved: message from server
Client 789 recieved: message from server
Client 123 recieved: Unregistered
Client 456 recieved: Unregistered
Client 789 recieved: Unregistered
DONT HAVE ANY CLIENT!
Related
I've been trying to solve this simple problem, but I cannot make it work.
I am using WebSocketSharp.Server. The code can be seen below.
In my NetworkClass I have someData I would like to send to the client when a message is received. The problem is the OnMessage event gets fired in a different class, and I don't know how the access the instance of this class.
Broadcasting to all clients form the NetworkClass works fine and receiving messages form the client works fine as well.
public class IndexRoute : WebSocketBehavior {
protected override void OnMessage(MessageEventArgs e) {
Console.WriteLine("Received message form client: "+e.Data);
//TODO: send someData string to client
}
}
public class NetworkClass {
String someData = "TestData";
WebSocketServer server = new WebSocketServer("ws://127.0.0.1:5000");
public NetworkClass() {
server.AddWebSocketService<IndexRoute>("/");
server.Start();
Console.WriteLine("Server started");
}
public void broadcastData() {
server.WebSocketServices["/"].Sessions.Broadcast(someData);
Console.WriteLine("Broadcast");
}
}
I combined the answers of Jeroen van Langen and Jesper. The key was to pass the instance of the NetworkClass to the IndexRoute class and access the variables from there.
server.AddWebSocketService<IndexRoute>("/", () => new IndexRoute(this));
works but is marked as obsolete.
public class IndexRoute : WebSocketBehavior {
private NetworkClass _instanceOfNetworkClass;
public IndexRoute(NetworkClass instanceOfNetworkClass)
{
_instanceOfNetworkClass = instanceOfNetworkClass;
}
protected override void OnMessage(MessageEventArgs e) {
Console.WriteLine("Received message form client: "+e.Data);
//Broadcast someData string to clients
Sessions.Broadcast(_instanceOfNetworkClass.someData);
}
}
public class NetworkClass {
public String someData = "TestData";
WebSocketServer server = new WebSocketServer("ws://127.0.0.1:5000");
public NetworkClass() {
server.AddWebSocketService<IndexRoute>("/", () => new IndexRoute(this));
server.Start();
Console.WriteLine("Server started");
}
public void broadcastData() {
server.WebSocketServices["/"].Sessions.Broadcast(someData);
Console.WriteLine("Broadcast");
}
}
I don't have any experience with WebSocketSharp, but the docs says you can give an alternate WebSocketBehavior construction function to the AddWebSocketService<>
Let me know if it works: (else i'll remove it)
public class IndexRoute : WebSocketBehavior {
private string _someData;
// define the constructor which accepts the someData
// save it in a field.
public IndexRoute(string someData)
{
_someData = someData;
}
protected override void OnMessage(MessageEventArgs e) {
Console.WriteLine("Received message form client: "+e.Data);
//TODO: send someData string to client
// do something with _someData
}
}
public class NetworkClass {
String someData = "TestData";
WebSocketServer server = new WebSocketServer("ws://127.0.0.1:5000");
public NetworkClass() {
// pass the construction function.
// (construct the IndexRoute and pass the someData to it.)
server.AddWebSocketService<IndexRoute>("/", () => new IndexRoute(someData));
server.Start();
Console.WriteLine("Server started");
}
public void broadcastData() {
server.WebSocketServices["/"].Sessions.Broadcast(someData);
Console.WriteLine("Broadcast");
}
}
I didn't tested it, but it might give you a step in the right direction to solve it.
When you inherit WebSocketBehavior, you get methods and properties that allow you to find out information about the connection you are currently talking to. In this case, just use one of the Send methods to send to the connection that sent the message:
protected override void OnMessage(MessageEventArgs e) {
Console.WriteLine("Received message form client: "+e.Data);
Send(/* pick one of the overloads to suit your needs */);
}
You can also use the property Context to get a WebSocketContext with information about the connection, or ID to find the session (connection) ID, which you could pass to another object. If the question is how you find your instance of NetworkClass, you are already constructing the IndexRoute yourself, just pass this in as an additional parameter.
Below you can see a simplified version of my SignalR self hosted hub on a windows service:
public static class SubscriptionHandler
{
public static int PriceFeedMembersCount = 0;
}
public class PriceHub : Hub
{
public Task SubscribeToPriceFeed()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
if (SubscriptionHandler.PriceFeedMembersCount == 0)
{
context.Clients.All.updatePriceSubscriptionStatus(true);
}
SubscriptionHandler.PriceFeedMembersCount++;
return context.Groups.Add(Context.ConnectionId, "PriceFeed");
}
public Task UnsubscribeFromPriceFeed()
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
SubscriptionHandler.PriceFeedMembersCount--;
if (SubscriptionHandler.PriceFeedMembersCount == 0)
{
context.Clients.All.updatePriceSubscriptionStatus(false);
}
return context.Groups.Remove(Context.ConnectionId, "PriceFeed");
}
public void NotifySubscribers(Price price)
{
IHubContext context = GlobalHost.ConnectionManager.GetHubContext<PriceHub>();
context.Clients.Group("PriceFeed").updatePrice(price);
}
}
And I have two types of clients for that hub: One of them is web applications and the other one is windows services. Here you can see a demo implementation for my windows service as a signalr client:
public partial class WinSer45 : ServiceBase
{
private HubConnection hubConnection;
private IHubProxy priceProxy;
private Timer timer = new Timer();
private bool hasSubscribers = false;
public WinSer45()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
timer.Interval = 1000; // saniyede bir
timer.Elapsed += timer_Elapsed;
timer.Enabled = true;
hubConnection = new HubConnection("http://localhost:8080/signalr", useDefaultUrl: false);
priceProxy = hubConnection.CreateHubProxy("PriceHub");
hubConnection.Start().Wait();
priceProxy.On<bool>("UpdatePriceSubscriptionStatus", hasSubscribers =>
{
this.hasSubscribers = hasSubscribers;
});
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
if (hasSubscribers)
{
TestPrice testPrice = new TestPrice() { Id = 1, Buy = 1.2345, Sell = 9.8765, Symbol = "EURUSD" };
priceProxy.Invoke("NotifySubscribers", testPrice).Wait();
}
}
protected override void OnStop()
{
}
}
As you see I use the hasSubscribers flag to minimize the messages between hub and clients. And hasSubscribers flag is changed by SubscribeToPriceFeed and UnsubscribeFromPriceFeed methods.
If you look carefully you see the line below in SubscribeToPriceFeed:
context.Clients.All.updatePriceSubscriptionStatus(true);
I don't want to send the message to all clients but my client windows service. How can I store the connection Id of a specific client in my hub? If I can do that, I know I can send message to a specific connectionId as in the line below:
context.Clients.Client(connectionId).updatePriceSubscriptionStatus(true);
Thanks in advance,
pass source during connection
like this
hubConnection = new HubConnection("http://localhost:8080/signalr","source=windows",useDefaultUrl: false);
HUB
public override Task OnConnected()
{
var source= Context.QueryString['source'];
return base.OnConnected();
}
create a class which will hold the user with source
public class user {
public string ConnectionID {set;get;}
public string Source {set;get;}
}
declare a list in the hub
List<user> userList=new List<user>();
Then push the user during OnConnected
public override Task OnConnected()
{
var us=new user();
us.Source = Context.QueryString['source'];
us.ConnectionID=Context.ConnectionId;
userList.Add(us);
return base.OnConnected();
}
and during broadcast just filter it by source
var windowsUser=userList.Where(o=>o.Source == "windows").ToList(); // you'll get the windows user list
I'm kind of new to this ask-answer thing, please let me know if I've done any mistakes. I have this server program, running on my laptop. Server is a console application;
class Program
{
static void Main(string[] args)
{
Server sv = new Server("192.168.2.69", 52025);
sv.OnClientAccept += new ClientAcceptHandler(sv_OnClientAccept);
sv.OnClientMessage += new ClientMessageHandler(sv_OnClientMessage);
sv.Start();
}
static void sv_OnClientMessage(Server s, System.Net.Sockets.TcpClient client, string message)
{
Console.WriteLine("Message received from client " + GetClientIp(client) + ": \"" + message + "\"");
string msgToAll = message;
s.SendToAllClients(msgToAll);
Console.WriteLine("Message sent: \"" + message + "\" to the clients:");
foreach (TcpClient cl in s.Clients)
{
Console.WriteLine(GetClientIp(cl));
}
}
static void sv_OnClientAccept(Server s, System.Net.Sockets.TcpClient client)
{
Console.WriteLine("Client Accepted : " + GetClientIp(client));
}
static string GetClientIp(TcpClient Client)
{
return ((IPEndPoint)Client.Client.RemoteEndPoint).Address.ToString();
}
}
The Server class;
public delegate void ClientAcceptHandler(Server s, TcpClient client);
public delegate void ClientMessageHandler(Server s, TcpClient client, string message);
public class Server
{
private List<TcpClient> clients = new List<TcpClient>();
object lockObjc;
private TcpListener server;
private string ip;
private int port;
private Thread accepter, listener;
public List<TcpClient> Clients { get { return this.clients; } set { this.clients = value; } }
public event ClientAcceptHandler OnClientAccept;
public event ClientMessageHandler OnClientMessage;
public Server(string IP, int Port)
{
ip = IP;
port = Port;
}
private void ClientAccepted(TcpClient Client)
{
if (OnClientAccept != null)
{
OnClientAccept.Invoke(this, Client);
}
}
private void ClientMessaged(TcpClient Client, string Message)
{
if (OnClientMessage != null)
{
OnClientMessage.Invoke(this, Client, Message);
}
}
public void Start()
{
lockObjc = new object();
IPAddress ipAddress = IPAddress.Parse(ip);//127.0.0.1 -> local || "192.168.2.69" -> laptop
server = new TcpListener(ipAddress, port);//2014 -> local || 52025
server.Start();
accepter = new Thread(AcceptClients);
accepter.Start();
listener = new Thread(Listen);
listener.Start();
}
private void AcceptClients()
{
while (true)
{
TcpClient attachedCl = server.AcceptTcpClient();
if (attachedCl != null)
{
lock (lockObjc)
{
if (!clients.Contains(attachedCl))
{
clients.Add(attachedCl);
ClientAccepted(attachedCl);
}
}
}
}
}
private void Listen()
{
while (true)
{
for (int i = 0; i < clients.Count; i++)
{
TcpClient client = clients[i];
lock (lockObjc)
{
try
{
StreamReader clientIn = new StreamReader(client.GetStream());
string msg = clientIn.ReadLine();
if (msg != string.Empty)
{
ClientMessaged(client, msg);
}
}
catch
{
}
}
}
}
}
private bool send(TcpClient Client, string Msg)
{
bool b = true;
try
{
TcpClient client = Client;
StreamWriter clientOut = new StreamWriter(client.GetStream());
clientOut.AutoFlush = true;
clientOut.WriteLine(Msg);
}
catch
{
b = false;
}
return b;
}
public bool SendToACLient(TcpClient Client, string Message)
{
return send(Client, Message);
}
public bool SendToAClient(int i, string Message)
{
return send(clients[i], Message);
}
public bool SendToAllClients(string Message)
{
bool b = true;
for (int i = 0; i < clients.Count; i++)
{
b = b && send(clients[i], Message);
}
return b;
}
public bool SendToAllClientsExcept(TcpClient Client, string Message)
{
int x = clients.IndexOf(Client);
bool b = true;
for (int i = 0; i < clients.Count; i++)
{
if (i != x)
{
b = b && send(clients[i], Message);
}
}
return b;
}
}
Since I'm really new to server-client relationships, I don't know if the server part is OK, but it seems OK to me programmatically (But I'm also amateur programer, no real education).
And the client part is;
public delegate void ServerMessageHandler(Client Receiver, string Message);
public class Client
{
private StreamReader clientIn;
private StreamWriter clientOut;
private TcpClient client;
private Thread listener;
private object lockObj;
public event ServerMessageHandler OnServerMessage;
public bool Connected { get { return (client != null && client.Connected); } }
public Client()
{
lockObj = new object();
client = new TcpClient();
listener = new Thread(Listen);
}
private void ServerMessaged(string Message)
{
if (OnServerMessage != null)
{
OnServerMessage.Invoke(this, Message);
}
}
private void Listen()
{
string serverMsg;
while (true)
{
try
{
serverMsg = clientIn.ReadLine();
if (serverMsg != string.Empty)
{
ServerMessaged(serverMsg);
}
}
catch
{
}
}
}
private void start()
{
listener.Start();
}
public bool Connect(string Ip, int Port)
{
client.Connect(Ip, Port);//"192.168.2.69", 52025
if (client.Connected)
{
clientIn = new StreamReader(client.GetStream());
clientOut = new StreamWriter(client.GetStream());
clientOut.AutoFlush = true;
start();
}
return client.Connected;
}
public void Send(string Message)
{
if (client.Connected)
{
clientOut.WriteLine(Message);
}
}
}
Here's the form that I run Client class;
public partial class Form1 : Form
{
string s;
Client c;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
c = new Client();
c.OnServerMessage += new ServerMessageHandler(c_OnServerMessage);
bool b = c.Connect("192.168.2.69", 52025);
if (b)
{
s += "Connected to the server: 192.168.2.69:52025\r\n";
}
timer1.Start();
}
void c_OnServerMessage(Client Receiver, string Message)
{
s += "Server: " + Message + "\r\n";
}
private void button1_Click(object sender, EventArgs e)
{
c.Send(textBox1.Text);
}
private void timer1_Tick(object sender, EventArgs e)
{
textBox2.Text = s;
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
c.Send(textBox1.Text);
}
}
}
This form has two textboxes, first one is the one which takes user input (textBox1), the second one is the one which shows server responds. Why I'm not using Console? Because I've tried it in a way which I was waiting an input from user (Console.ReadLine) which as far as I know locks the console until user presses enter, even tough I'm using a thread for listening the server, I wasn't able to show the server answer on console.
So, I decided to create my own console (sort-of). The reason I run a timer to show messages is I get an error when I try to change the textbox text from a method that is being called by a thread (which is the c_OnServerMessage method, being called, indirectly, from the Listener thread from Client class)
But the problem I get here is this: I run the server on my laptop, I also run one client on my laptop which goes perfectly fine until I open up another client on another computer. At that point things go this way: I send a message from a client, the message reaches the server and is sent back. When I send another message, that message does not reach the server until I send a message from Client 2. And when I send a message from Client 2, the server gets the message from Client 2 even tough I sent the message from Client 1 first.
So basically what happens is, if I run 2 clients, I cannot send 2 messages in a row from a client, it kind of acts like a chess game where there is a turn for playing. I really don't understand the reason.
This problem is probably from a basic mistake but I had to write this whole message to be able to express myself. Thank you for your patient and your helps.
EDIT:
Problem solved thanks to this: TCP server with multiple Clients
My problem was the Listen method from Server class. The Listen method is being called by a thread, but still it runs a for loop in itself. Which if loop stops and waits for something, thread wouldn't make any difference. Thanks again, i think i will keep question, because i do not know what should happen to solved problems.
Im trying to forward an event OnClientMessage from my class Client over the class Server to outside my libary.
Client.cs
public class Client
{
private TcpClient tcpClient;
private StreamWriter writer;
private Boolean alive = true;
private int id;
public delegate void OnClientMessageHandler(Client sender, String message);
public delegate void OnClientDisconnectHandler(Client sender);
public event OnClientMessageHandler OnClientMessage;
public event OnClientDisconnectHandler OnClientDisconnect;
public Client(TcpClient tcpClient, int id)
{
this.tcpClient = tcpClient;
this.id = id;
writer = new StreamWriter(tcpClient.GetStream());
new Thread(() =>
{
Listen(new StreamReader(tcpClient.GetStream()));
}).Start();
}
void Listen(StreamReader reader)
{
while (tcpClient.GetStream().DataAvailable && alive)
{
OnClientMessage(this, reader.ReadLine());
Thread.Sleep(150);
}
}
public void Write(String message)
{
writer.WriteLine(message);
writer.Flush();
}
public int GetID()
{
return id;
}
public void Close()
{
alive = false;
writer.Close();
tcpClient.Close();
OnClientDisconnect(this);
}
}
Server.cs
public class Server
{
private IPAddress serverIP;
private short serverPort;
private TcpListener serverListener;
private int serverClientCount;
public List<Client> serverClients = new List<Client>();
private Boolean running;
public delegate void OnClientMessageHandler(Client sender, String message);
public delegate void OnClientDisconnectHandler(Client sender);
public event OnClientMessageHandler OnClientMessage;
public event OnClientDisconnectHandler OnClientDisconnect;
public Server(IPAddress ip, short port, Boolean autoStart = true)
{
this.serverIP = ip;
this.serverPort = port;
if(autoStart)
OpenServer();
}
public void OpenServer()
{
serverListener = new TcpListener(serverIP, serverPort);
serverListener.Start();
running = true;
while (running)
{
if (serverListener.Pending())
{
TcpClient tcpClient = serverListener.AcceptTcpClient();
new Thread(() =>
{
Client client;
client = new Client(tcpClient, serverClientCount);
client.OnClientMessage += new Client.OnClientMessageHandler(OnClientMessage);
client.OnClientDisconnect += new Client.OnClientDisconnectHandler(OnClientDisconnect);
serverClients.Add(client);
serverClientCount++;
}).Start();
}
else
{
Thread.Sleep(150);
}
}
}
public void WriteToClient(Client client, String message)
{
client.Write(message);
}
public void WriteToAll(String message)
{
serverClients.ForEach(client => client.Write(message));
}
public void Shutdown()
{
running = false;
serverClients.ForEach(client => client.Close());
serverListener.Stop();
}
}
Now when the event is firing the application crashes with Delegate to an instance method cannot have null 'this'.
Are I'm doing something wrong or isn't this the right way to forward an event?
This is pretty unique, never once seen anybody do this. It is a regression in the .NET Framework, 3.5 gives you a much better exception. Basic problem is that you made the event subscribe itself. A simple version to repro that crash:
using System;
class Program {
public static event Action Kaboom;
static void Main(string[] args) {
Kaboom += new Action(Kaboom); // 3.5 raises an exception here
var handler = Kaboom;
if (handler != null) handler(); // kaboom
}
}
You are not actually "forwarding" the event. Untangle your names and code. Add, say, a Fire() method.
What's the most simple way that a WCF Service, that's being hosted by a console application , can interact with the said console application, to do a Console.WriteLine() ie.
Some code:
The contract:
[ServiceContract(Name = "IProdsService")]
public interface IProdsService
{
[OperationContract(Name = "Alert",IsOneWay=true)]
void Alert(string msg);
}
The Service:
public class ProdsService : IProdsService
{
//IProdsService.Alert implementation
public void Alert(string msg)
{
//TODO: Send Alert to Console Application!
}
}
The Console App:
class Program
{
static void Main(string[] args)
{
ServiceHost prodService = new ServiceHost(typeof(ProdsService));
ServiceDescription serviceDesciption = prodService.Description;
prodService.Open();
Console.ReadLine();
}
}
Following is an example of running host and client where host can log message on the console. On your example, I am not sure why you have set IsOneWay=true. For this specific case, one way is not what you want. Also, I have used net.tcp binding in the following example; it should work with any other binding as well.
Basically in the example, user's entry is sent to the host service which echos the message on the console.
[ServiceContract]
public interface IProdsService
{
[OperationContract]
void Alert(string msg);
}
/// <summary>
/// Host Class
/// </summary>
public class ProdsService : IProdsService
{
public ProdsService()
{
Console.WriteLine("Service instantiated.");
}
public void Alert(string msg)
{
Console.WriteLine(msg);
}
}
/// <summary>
/// Client proxy wrapper
/// </summary>
public class ProdsServiceClient : ClientBase<IProdsService>, IProdsService
{
public ProdsServiceClient()
{
}
public ProdsServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
base(binding, remoteAddress)
{
}
public void Alert(string msg)
{
base.Channel.Alert(msg);
}
}
class Program
{
static ManualResetEvent _reset;
static void Main(string[] args)
{
string host = "localhost";
int port = 8888;
//ManualResetEvent is used for syncing start/stop of service.
_reset = new ManualResetEvent(false);
var action = new Action<string, int>(Start);
var result = action.BeginInvoke(host, port, null, null);
//Wait for svc startup, this can be synced with resetEvents.
Thread.Sleep(2000);
//Create a client instance and send your messages to host
using (var client = new ProdsServiceClient(new NetTcpBinding(), new EndpointAddress(string.Format("net.tcp://{0}:{1}", host, port))))
{
client.Alert("Test message");
string msg = string.Empty;
do
{
Console.Write("Type a message to send (X to exit): ");
msg = Console.ReadLine();
client.Alert(msg);
}
while (!msg.Trim().ToUpper().Equals("X"));
}
//Signal host to stop
_reset.Set();
action.EndInvoke(result);
Console.Write("Press any to exit.");
Console.ReadKey();
}
static void Start(string host, int port)
{
string uri = string.Format("net.tcp://{0}:{1}", host, port);
//var server = new ProdsService();
ServiceHost prodService = new ServiceHost(typeof(ProdsService));
prodService.AddServiceEndpoint(typeof(IProdsService), new NetTcpBinding(), uri);
Console.WriteLine("Service host opened");
prodService.Open();
//Wait until signaled to stop
_reset.WaitOne();
Console.WriteLine("Stopping host, please wait...");
prodService.Close();
Console.WriteLine("Service host closed");
}
}
duh, my bad, just calling console.writeline from the alert operation does it, i was being fooled by the oneway and was not getting an error...so that's no more oneways for me...