我需要阻止,直到我的一个管道中有数据被读取。
我已经尝试过WaitForMultipleObjects,但它只是立即返回说其中一个管道有数据。管道块上的后续ReadFile。
我无法使用PeekNamedPipe,因为我需要阻止直到数据可用,并且在睡眠循环中偷看会因睡眠而导致延迟反应。
这段代码是跨平台的,一切都在linux上运行得很好,因为我可以在一组fifo fd' s上使用Select,然后在select返回时从那个就读的那个读取,但是没有似乎在Windows上是等效的。
我见过很多人说你必须使用带有读/写的重叠操作,但是这不会要求我循环并尝试读取每一个管道吗?
是否有一个阻塞操作阻塞,直到其中一个管道中有数据?
答案 0 :(得分:2)
我已经尝试过WaitForMultipleObjects,但它只是立即返回说其中一个管道有数据。管道块上的后续ReadFile。
MSDN的可等待对象类型列表中未提及管道,因此您无法将管道传递给任何WaitFor...()
系列函数。
我见过很多人说你必须使用带有读/写的重叠操作,但是这不会要求我循环并尝试读取每一个管道吗?
重叠的I / O是解决您问题的方法。
以重叠模式创建管道。然后你可以:
通过CreateEvent()
创建一个事件对象,并将其分配给您用于给定读取操作的OVERLAPPED
结构。然后,您可以在多个管道上发出异步ReadFile/Ex()
操作,并使用WaitForMultipleObject()
等待事件对象,直到其中一个发出信号。 WaitForMultipleObjects()
的返回值将告诉您哪个事件已发出信号,并通过关联哪个管道已读取某些数据。
使用GetQueuedCompletionStatus/Ex()
代替WaitForMultipleObjects()
,然后您可以省略事件对象。 GetQueuedCompletionStatus/Ex()
会告诉您哪些特定的OVERLAPPED
结构已经完成(如果需要,您可以使用hEvent
字段传递用户定义的数据。)
MSDN文档中对此进行了介绍:
Synchronous and Overlapped Pipe I/O
select()
可以在一次通话中报告多个已完成的操作。但是,WaitForMultipleObjects()
和GetQueuedCompletionStatus()
一次只能报告一个已完成的操作。您必须在循环中调用它们以发现是否已完成多个操作。另一方面,GetQueuedCompletionStatusEx()
可以一次报告多个已完成的操作。
是否有一个阻塞操作阻塞,直到其中一个管道中有数据?
是。见上文。
答案 1 :(得分:-1)
是的,使用重叠I / O是最佳选择。您可以将每个管道句柄绑定到I / O完成端口(直接通过CreateIoCompletionPort()
,或间接通过BindIoCompletionCallback()
)。对于异步读取,创建一个继承自OVERLAPPED
的结构,并使用管道句柄将其传递给ReadFile/Ex()
。每次读取都需要自己分配的该结构实例。然后,您可以使用GetQueuedCompletionStatus()
(或绑定回调)来检测每次读取的完成时间。你不需要任何循环。