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
,当有人连接时,告诉他们离开,直到他们等待了给定的时间,然后关闭管道。