I'm using code from this article with only difference that maxNumberOfServerInstances is set to -1 (number of server instances with the same pipe name is limited only by system resources) in NamedPipeServerStream constructor
Async Listen Method [Listen Server Class]:
class PipeServer
{
string _pipeName;
public void Listen(string PipeName)
{
try
{
// Set to class level var so we can re-use in the async callback method
_pipeName = PipeName;
// Create the new async pipe
NamedPipeServerStream pipeServer = new NamedPipeServerStream(PipeName,
PipeDirection.In, -1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
// Wait for a connection
pipeServer.BeginWaitForConnection
(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}
catch (Exception oEX)
{ ... }
}
private void WaitForConnectionCallBack(IAsyncResult iar)
{
try
{
// Get the pipe
NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
// End waiting for the connection
pipeServer.EndWaitForConnection(iar);
// Read the incoming message
byte[] buffer = new byte[255];
pipeServer.Read(buffer, 0, 255);
// Convert byte buffer to string
string stringData = Encoding.UTF8.GetString(buffer, 0, buffer.Length);
...
// Kill original sever and create new wait server
pipeServer.Close();
pipeServer = null;
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In,
-1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
// Recursively wait for the connection again and again....
pipeServer.BeginWaitForConnection(
new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}
catch
{ ... }
}
}
Async Send Method [PipeClient Class]
class PipeClient
{
public void Send(string SendStr, string PipeName, int TimeOut = 1000)
{
try
{
NamedPipeClientStream pipeStream = new NamedPipeClientStream
(".", PipeName, PipeDirection.Out, PipeOptions.Asynchronous);
// The connect function will indefinitely wait for the pipe to become available
// If that is not acceptable specify a maximum waiting time (in ms)
pipeStream.Connect(TimeOut);
byte[] _buffer = Encoding.UTF8.GetBytes(SendStr);
pipeStream.BeginWrite
(_buffer, 0, _buffer.Length, new AsyncCallback(AsyncSend), pipeStream);
}
catch (TimeoutException oEX)
{ ... }
}
private void AsyncSend(IAsyncResult iar)
{
try
{
// Get the pipe
NamedPipeClientStream pipeStream = (NamedPipeClientStream)iar.AsyncState;
// End the write
pipeStream.EndWrite(iar);
pipeStream.Flush();
pipeStream.Close();
pipeStream.Dispose();
}
catch (Exception oEX)
{ ... }
}
}
And I have two WinForms applications: server only have Listen button (clicking results in Listen method call), client has textBox for text input and Send button (clicking results in Send method call).
I do the following:
- start multiple copies of server application (as the result - multiple instances of NamedPipeServerStream with the same pipe name are created)
- click Listen button in each of them
- start client application
- click Send button
That results in receiving message by only one server application (that one, whose Listen button was clicked first). If I click Send button one more time - message is received by second-clicked server application. So instances receive messages in order of pressing Listen button on them and that repeats in cycle (but I'm not 100% sure that such order will be the same under all conditions).
Such behavior is strange for me: I've expected message to be received by all instances at the same time.
Could someone explain me why it is happening in such way?
How can I deliver message to all instaces with one Send button click?