我找不到一个很好的例子,说明如何创建一个异步运行的可重用命名管道侦听器。我可以成为一个可重复使用的听众:
NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut);
while (true)
{
pipeServer.WaitForConnection();
StreamReader reader = new StreamReader(pipeServer);
MessageBox.Show(reader.ReadLine());
pipeServer.Disconnect();
}
我可以做一个异步听众:
NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
pipeServer.BeginWaitForConnection((a) =>
{
pipeServer.EndWaitForConnection(a);
StreamReader reader = new StreamReader(pipeServer);
MessageBox.Show(reader.ReadLine());
}, null);
但我似乎无法兼得。这有一个很好的例子吗?我也担心部分发送的消息,因为我认为这是异步通信的问题。
更新: 我离我更近了。
pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
pipeServer.BeginWaitForConnection((a) =>
{
pipeServer.EndWaitForConnection(a);
StreamReader reader = new StreamReader(pipeServer);
while (running)
{
String text = reader.ReadLine();
if (String.IsNullOrEmpty(text) == false)
{
MessageBox.Show(text);
}
}
MessageBox.Show("Done!");
}, null);
这将成功读取一次,并将继续循环,ReadLine在初始成功读取后返回空的空字符串。所以它显然没有阻止,并试图再次阅读。问题是如果我第二次发送相同的消息,它不会被拾取,我的管道编写者说它收到错误2316(虽然我无法弄清楚这意味着什么)。我想我只需要做一些类似于每次管道清理的事情,就像我列出的第一个代码示例一样,但我还没有完成工作。
答案 0 :(得分:7)
我想我已经明白了:
pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
Boolean connectedOrWaiting = false;
Byte[] buffer = new Byte[65535];
while (running)
{
if (!connectedOrWaiting)
{
pipeServer.BeginWaitForConnection((a) => { pipeServer.EndWaitForConnection(a); }, null);
connectedOrWaiting = true;
}
if (pipeServer.IsConnected)
{
Int32 count = pipeServer.Read(buffer, 0, 65535);
if (count > 0)
{
UTF8Encoding encoding = new UTF8Encoding();
String message = encoding.GetString(buffer, 0, count);
MessageBox.Show(message);
}
pipeServer.Disconnect();
connectedOrWaiting = false;
}
}
这将接受多条消息,并在运行设置为false时立即关闭(显然在另一个线程中)。这似乎是我需要的。有人可以证实我没有做任何愚蠢的事吗?
答案 1 :(得分:2)
我也关注部分发送的消息
使用本机(Win32)API的NamedPipes不是问题,所以我非常怀疑它们是使用.NET的问题。但是在native documentation它确实说:
数据作为消息流写入管道。管道将每次写入操作期间写入的字节视为消息单元。当未完全读取消息时,GetLastError函数返回ERROR_MORE_DATA。此模式可与PIPE_READMODE_MESSAGE或PIPE_READMODE_BYTE一起使用。
(注意ERROR_MORE_DATA
是234。)
文档还说,对于标记FILE_FLAG_OVERLAPPED
(本地等效于PipeOptions.Asynchronous
):
启用重叠模式。如果启用此模式,则执行可能需要很长时间才能完成的读取,写入和连接操作的函数可以立即返回。
我总是使用异步命名管道进行异步IO操作(即Stream.BeginRead
),但这确实意味着失去TextReader
的功能,但后来PipeTransmissionMode.Message
被定义为术语无论如何都要传输字节组。