WaitNamedPipe 函数允许管道客户端应用程序同步等待命名管道服务器上的可用连接。然后,您调用 CreateFile 作为客户端打开管道。伪代码:

// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
    if (WaitNamedPipe says connection is ready) {
        hPipe = CreateFile(...);
        if (hPipe ok or last error is NOT pipe busy) {
            break; // hPipe is valid or last error is set
        }
    } else {
        break; // WaitNamedPipe failed
    }
}

问题在于这些都是阻塞的同步调用。异步执行此操作的好方法是什么?例如,我似乎找不到使用重叠I/O的API。例如,对于管道服务器, ConnectNamedPipe 函数提供了lpOverlapped参数,允许服务器异步等待客户端。然后,管道服务器可以调用WaitForMultipleObjects并等待I/O操作完成,或者等待任何其他事件被发出信号(例如,一个事件通知线程取消挂起的I/O并终止)。

我能想到的唯一方法是在一个短而有限的超时循环中调用WaitNamedPipe,并检查其他信号是否超时。或者,在循环中调用CreateFile,检查其他信号,然后以较短的延迟(或Sleep)调用WaitNamedPipe。例如:
HANDLE hPipe;
while (true) {
    hPipe = CreateFile(...);
    if (hPipe not valid and pipe is busy) {
        // sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
        Sleep(100);
        // TODO: check other signals here to see if we should abort I/O
    } else
        break;
}

但是在我看来,这种方法会散布在高高的天堂上。如果管道暂时无法使用,则该线程将继续运行-消耗CPU资源,使用电源,要求将内存页面保留在RAM中等。在我看来,依赖Sleep或短暂超时的线程不能很好地执行这是草率的多线程编程的标志。

但是在这种情况下,有什么选择呢?

最佳答案

WaitNamedPipe完全没有用,如果您指定了超时并且没有服务器在等待它,它将仅使用所有cpu。

只需像执行操作一样用CreateFile反复调用Sleep,然后将其移动到其他线程即可。没有其他选择。
WaitNamedPipe唯一提供的“好处”是,如果您想知道是否可以连接到命名管道,但是明确不想实际打开连接。是垃圾

如果您真的想彻底了解,唯一的选择是

  • 确保已打开命名管道的任何程序始终在连接命名管道后立即再次调用CreateNamedPipe
  • 让您的程序实际检查该程序是否正在运行。
  • 如果您的意图实际上是没有其他连接,请仍然调用CreateNamedPipe,当有人连接时,告诉他们离开,直到他们等待了给定的时间,然后关闭管道。
  • 10-08 08:16