6

我找不到一个很好的例子来说明如何创建一个异步运行的可重用命名管道侦听器。我可以制作一个可重用的侦听器:

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(尽管我无法弄清楚这意味着什么)。我想我只需要做一些类似于每次清理管道的事情,就像我列出的第一个代码示例一样,但我还没有让它工作。

4

2 回答 2

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 时立即关闭(显然在另一个线程中)。这似乎是我需要的。有人可以验证我没有做任何愚蠢的事情吗?

于 2010-09-28T20:17:59.107 回答
2

我也担心部分发送的消息

它们不是使用本机 (Win32) API 的 NamedPipes 的问题,所以我非常怀疑它们是使用 .NET 的问题。但是在本机文档中确实说:

数据作为消息流写入管道。管道将每个写入操作期间写入的字节视为一个消息单元。GetLastError 函数在未完全读取消息时返回 ERROR_MORE_DATA。此模式可与 PIPE_READMODE_MESSAGE 或 PIPE_READMODE_BYTE 一起使用。

(注ERROR_MORE_DATA为 234。)

该文档还说,对于标志FILE_FLAG_OVERLAPPED(的本机等效项PipeOptions.Asynchronous):

启用重叠模式。如果启用此模式,则执行读取、写入和连接操作可能需要很长时间才能完成的函数可以立即返回。

我一直将异步 IO 操作与异步命名管道(即Stream.BeginRead)一起使用,但这确实意味着失去了 a 的功能TextReader,但PipeTransmissionMode.Message无论如何都是根据传输字节组来定义的。

于 2010-09-28T16:05:43.817 回答