WaitNamedPipe的重叠I/O替代方法是什么?

Jam*_*ton 6 c c++ windows named-pipes

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
    }
}
Run Code Online (Sandbox Code Playgroud)

问题是这些都是阻塞的同步调用.异步执行此操作的好方法是什么?例如,我似乎无法找到使用重叠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;
}
Run Code Online (Sandbox Code Playgroud)

但是在我看来,这种方法对于天堂来说很臭.如果管道暂时不可用,则线程继续运行 - 使用电源吸收CPU,需要将内存页保留在RAM中等等.在我看来,依赖于Sleep或短暂超时的线程表现不佳,是一种草率的多线程编程的标志.

但在这种情况下,替代方案是什么?

fcr*_*ick 5

WaitNamedPipe 完全没用,如果指定超时并且没有服务器等待它,它将只使用所有cpu.

只需要像你正在做CreateFileSleep那样一遍又一遍地调用,并根据需要将其移动到其他线程.没有API替代品.

唯一的"好处" WaitNamedPipe是,如果您想知道是否可以连接到命名管道但是您明确不想实际打开连接.这是垃圾.

如果你真的想要彻底,你唯一的选择是

  • 确保打开命名管道的任何程序始终CreateNamedPipe在连接命名管道后立即再次调用.
  • 让您的程序实际检查该程序是否正在运行.
  • 如果你的意图真的没有额外的连接,仍然打电话CreateNamedPipe,当有人连接时,告诉他们离开,直到他们等待一段时间,关闭管道.