Reputation: 487
I have 2 applications communicating using named pipes.
Main program calls client program and creates pipe server to communicate with it. The client program creates pipe client. Main program can send any messages to client program and they should be handled on client side in some way. When client program is exiting, it is sending any message to main program and it means that server pipe should be closed.
I had no problem implementing the first part (sending messages from server to client) using server with PipeDirection.Out and client with PipeDirection.In. But when I tried to modify the code so that server and client are both having PipeDirection.InOut (to be able to send message from client to server), the code stopped working. The program hangs when I do writer.Flush (on server side) or writer.WriteByte (on client side). The places when it hangs now are marked as [HANGS HERE].
Server is created like this:
public static void CreatePipeServerStream()
{
var namedPipeServerStream = new NamedPipeServerStream("somename", PipeDirection.InOut);
namedPipeServerStream.WaitForConnection();
// This thread is wating for message from client
ThreadStart starter = () => WaitForSignalFromClient(namedPipeServerStream);
new Thread(starter).Start();
}
private static void WaitForSignalFromClient(NamedPipeServerStream namedPipeServerStream)
{
if (namedPipeServerStream.IsConnected)
{
namedPipeServerStream.ReadByte();
// we'll get here after something is read
// and if we got here, we should close the server pipe
// now I can get here only if I shut down the client program using Task manager
namedPipeServerStream.Close();
}
}
The procedure sending message to client is doing this (used to work when server had pipe direction == Out and client had pipe direction == In):
public static void SendMessageUsingPipe(NamedPipeServerStream namedPipeServerStream)
{
if (namedPipeServerStream.IsConnected)
{
var sw = new StreamWriter(namedPipeServerStream);
sw.WriteLine("smth");
// [HANGS HERE]
sw.Flush();
}
}
On the client side, this code is running in separate thread:
private void WaitServerCommands()
{
_pipe = new NamedPipeClientStream(".", "somename", PipeDirection.InOut);
using (var rdr = new StreamReader(_pipe))
{
while (true)
{
if (!_pipe.IsConnected)
{
_pipe.Connect();
}
rdr.ReadLine();
// I don't care what was sent by server, I just need to know that something was sent
Invoke(_handleCommand);
}
}
}
The code that is supposed to send message to server:
private void ClosePipes()
{
if (_pipe != null && _pipe.IsConnected)
{
// [HANGS HERE]
_pipe.WriteByte(113);
_pipe.WaitForPipeDrain();
_pipe.Close();
}
}
Any idea what is wrong with the code? Or maybe I miss something fundamental?
The actual problem is that I need to know on server side that the client has disconnected. Maybe it can be achieved in some other way?
Upvotes: 2
Views: 5451
Reputation: 1786
I don't think your setting the pipserver up correctly.
namedPipeServerStream.WaitForConnection() will block the current thread until a client connects.
When a client does connect you then read a byte from the client, at the same time you have the client reading a line from the server.
namedPipeServerStream.ReadByte();
rdr.ReadLine();
I'm guessing they are in stalemate waiting for one of them to send some info across.
Upvotes: 1