У меня есть 2 приложения, использующие именованные каналы.
Основная программа вызывает клиентскую программу и создает конвейерный сервер для связи с ней. Клиентская программа создает канал клиента. Основная программа может отправлять любые сообщения клиентской программе, и они должны каким-то образом обрабатываться на стороне клиента. Когда клиентская программа завершает работу, она отправляет любое сообщение основной программе, и это означает, что канал сервера должен быть закрыт.
У меня не было проблем с реализацией первой части (отправка сообщений с сервера на клиент) с использованием сервера с PipeDirection.Out и клиента с PipeDirection.In. Но когда я попытался изменить код так, чтобы сервер и клиент оба имели PipeDirection.InOut (чтобы можно было отправлять сообщения от клиента к серверу), код перестал работать. Программа зависает, когда я делаю writer.Flush (на стороне сервера) или writer.WriteByte (на стороне клиента). Места, в которых он висит, помечены как [ЗДЕСЬ ВЕДУЩИ].
Сервер создан так:
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();
}
}
Процедура отправки сообщения клиенту делает это (используется для работы, когда у сервера было направление трубы == Out, а у клиента было направление трубы == In):
public static void SendMessageUsingPipe(NamedPipeServerStream namedPipeServerStream)
{
if (namedPipeServerStream.IsConnected)
{
var sw = new StreamWriter(namedPipeServerStream);
sw.WriteLine("smth");
// [HANGS HERE]
sw.Flush();
}
}
На стороне клиента этот код выполняется в отдельном потоке:
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);
}
}
}
Код, который должен отправить сообщение на сервер:
private void ClosePipes()
{
if (_pipe != null && _pipe.IsConnected)
{
// [HANGS HERE]
_pipe.WriteByte(113);
_pipe.WaitForPipeDrain();
_pipe.Close();
}
}
Есть идеи, что не так с кодом? Или, может быть, я что-то упустил фундаментальное?
Фактическая проблема заключается в том, что мне нужно знать на стороне сервера, что клиент отключился. Может быть, это может быть достигнуто другим способом?