如何实现异步运行的可重用命名管道侦听器?

发布于 2024-09-24 23:37:38 字数 1616 浏览 1 评论 0原文

我找不到如何创建异步运行的可重用命名管道侦听器的好示例。我可以创建一个可重用的侦听器:

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

I can't find a good example of how to create a reusable named pipe listener that runs asynchronously. I can make a reusable listener:

NamedPipeServerStream pipeServer = new NamedPipeServerStream("MyPipe", PipeDirection.InOut);

    while (true)
    {
            pipeServer.WaitForConnection();

            StreamReader reader = new StreamReader(pipeServer);

            MessageBox.Show(reader.ReadLine());

            pipeServer.Disconnect();
    }

and I can make an asychronous listener:

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);

But I can't seem to get both going. Is there a good example for this? I'm also concerned about partially sent messages, as I believe that is an issue with asynchronous communications like this.

Update:
I'm a little closer.

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);

That will read successfully once, and will continue looping, with ReadLine returning an empty empty string after the initial successful read. So it's clearly not blocking, and is attempting to read again. The problem is if I send the same message a second time, it doesn't get picked up, and my pipe writer says it's receiving error 2316 (though I can't figure out what that means). I think I just need to do something similar to this where the pipe gets cleaned up each time, like the first code sample I listed, but I haven't gotten that to work yet.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

过度放纵 2024-10-01 23:37:38

我想我已经明白了:

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

I think I've got it:

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;
    }
}

This will accept multiple message as they come, and will shut down as soon as running is set to false (in another thread, obviously). It appears to be what I need. Can someone verify that I'm not doing anything silly?

无边思念无边月 2024-10-01 23:37:38

我还担心部分发送的消息

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

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

(注意 ERROR_MORE_DATA 为 234。)

文档还指出,对于标志 FILE_FLAG_OVERLAPPEDPipeOptions.Asynchronous 的本机等效项):

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

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

I'm also concerned about partially sent messages

They are not an issue with NamedPipes using the native (Win32) APIs, so I very much doubt they are a problem using .NET. However in the native documentation it does say:

Data is written to the pipe as a stream of messages. The pipe treats the bytes written during each write operation as a message unit. The GetLastError function returns ERROR_MORE_DATA when a message is not read completely. This mode can be used with either PIPE_READMODE_MESSAGE or PIPE_READMODE_BYTE.

(Note ERROR_MORE_DATA is 234.)

The documentation also says, for flag FILE_FLAG_OVERLAPPED (the native equivalent of PipeOptions.Asynchronous):

Overlapped mode is enabled. If this mode is enabled, functions performing read, write, and connect operations that may take a significant time to be completed can return immediately.

I've always used asynchronous IO operations with asynchronous named pipes (i.e. Stream.BeginRead), but this does mean losing the functionality of a TextReader, but then PipeTransmissionMode.Message is defined in terms of transmitting groups of bytes anyway.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文