如何让命名管道在 C# 中阻塞?

How do I get a Named Pipe to block in C#?

我正在编写一个 C# Windows 服务 (server),它需要从 C++ GUI 应用程序 (clients[=39] 接收消息=]) 很少使用 命名管道 ;可能需要几天到几周的时间才能收到消息。在我的测试中,我注意到它没有阻止数据进入,而是不断检查并打印换行符。它确实收到了测试消息,但我不得不使用 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 documentation 中找到了这个,同样的原理显然适用于 C#。

The server process must call DisconnectNamedPipe to disconnect a pipe handle from its previous client before the handle can be connected to another client by using the ConnectNamedPipe function.

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

StreamReader.ReadLine() 的文档说:

The next line from the input stream, or null if the end of the input stream is reached.

所以 ReadLine 正在返回 nullConsole.WriteLine(String) 在这种情况下会做什么?

If value is null, only the line terminator is written to the standard output stream.

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