如何在C#中获得要阻塞的命名管道

本文关键字:管道 | 更新日期: 2023-09-27 17:59:03

我正在编写一个C#Windows服务(服务器),该服务需要很少使用命名管道接收来自C++GUI应用程序(client的消息;收到消息可能需要几天到几周的时间。在我的测试中,我注意到它并没有阻止数据进入,而是不断地检查和打印换行符。它确实收到了测试消息,但我不得不使用Visual Studio中的调试器进行验证。

有没有一种方法可以让C#部分阻塞,直到真正有数据要接收?

--C#代码:

    var client = new NamedPipeServerStream("PipeTest");
    client.WaitForConnection();
    StreamReader reader = new StreamReader(client);
    while (true)
    {
        Console.WriteLine(reader.ReadLine());
    }  

--C++代码:

    DWORD written;
    INT error_code;
    CHAR buffer[1024];
    LPCWSTR pipe_name = L"''''.''pipe''PipeTest";
    LRESULT result;
    WaitNamedPipe(pipe_name, NMPWAIT_WAIT_FOREVER);
    HANDLE hpipe = CreateFile(pipe_name,
                              GENERIC_WRITE,
                              0,
                              NULL, 
                              OPEN_EXISTING,
                              FILE_ATTRIBUTE_NORMAL,
                              NULL);
    error_code = GetLastError();
    sprintf_s(buffer,"Sending Test Message");
    WriteFile(hpipe,buffer,strlen(buffer),&written,NULL);
    result = GetLastError();
    fprintf(stdout,"Pipe: %d Write: %d Written: %d",error_code,result,written);
    DisconnectNamedPipe(hpipe);
    CloseHandle(hpipe);
    std::cin.get();

[回答]

--带有更正名称的C#代码(server):

   var server = new NamedPipeServerStream("PipeTest");
   while (true)
   {
        server.WaitForConnection();
        StreamReader reader = new StreamReader(server);
        Console.WriteLine(reader.ReadLine());
        server.Disconnect();
   } 

对于这段代码,我只需要捕获一行数据,@The Shooter是正确的,但您需要添加server.Disconnect()才能再次阅读。我从C文档中发现了这一点,显然同样的原理在C#中也适用。

服务器进程必须调用DisconnectNamedPipe以断开管道句柄与其前一个客户端的连接,然后才能使用ConnectNamedPipe函数将句柄连接到另一个客户端。

如何在C#中获得要阻塞的命名管道

客户端正在断开管道连接,因此服务器在收到测试消息后立即看到输入流的结束。

StreamReader的文档。ReadLine()表示:

输入流的下一行,如果到达输入流的末尾,则为null。

所以ReadLine正在返回null;Console做什么。WriteLine(String)在这种情况下做什么?

如果值为null,则只将行终止符写入标准输出流。

QED。你所看到的行为与预期完全一样。

您需要检查从ReadLine返回的值,并适当地处理null。在这种情况下,您可能希望等待另一个连接。

代替:

var client = new NamedPipeServerStream("PipeTest");
client.WaitForConnection();
StreamReader reader = new StreamReader(client);
while (true)
{
    Console.WriteLine(reader.ReadLine());
}

试试这个:

var client = new NamedPipeServerStream("PipeTest");
while (true)
{
    client.WaitForConnection();
    StreamReader reader = new StreamReader(client);
    Console.WriteLine(reader.ReadLine());
}