重叠 I/O:如何在完成端口事件或正常事件上唤醒线程?
我想使用线程池来启动/取消重叠读取操作 - 分别使用 ReadFile()
和 CancelIo()
- 以及处理任何完成端口事件当读取操作完成时。
- 任何线程都可以发起读取操作
- 任何线程都可以处理读取完成事件
- 只有发起读取的线程可以取消它(这是
CancelIo()
限制)
我不确定如何实现这。 通常调用 GetQueuedCompletionStatus()
来等待完成端口事件,并调用 WaitForSingleObject()
来等待正常事件,但目前尚不清楚如何混合这两者。 如果 PostQueuedCompletionStatus() 让我指定一个特定的线程来唤醒我就可以了。 有任何想法吗?
更新:该解决方案必须在 Windows XP 上运行。 不幸的是,这排除了使用 CancelIoEx()
或 GetQueuedCompletionStatusEx()
的可能性。
I want to use a thread pool to both initiate/cancel overlapped read operations -- using ReadFile()
and CancelIo()
respectively -- as well as handling any completion port events when read operations complete.
- Any thread can initiate a read operation
- Any thread can handle a read-complete event
- Only the thread that initiated a read may cancel it (this is a
CancelIo()
limitation)
I'm not sure how to implement this. One normally calls GetQueuedCompletionStatus()
to wait on completion port events and WaitForSingleObject()
to wait on normal events but it's not clear how to mix the two. If PostQueuedCompletionStatus()
would let me specify a specific thread to wake up I'd be set. Any ideas?
UPDATE: The solution must run on Windows XP. Unfortunately this rules out using CancelIoEx()
or GetQueuedCompletionStatusEx()
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
1和2很简单,只需使用IO完成端口即可。
但是,正如您所发现的,3 个需要(在 Windows V61 之前)相同的线程。
如果使用 Windows >= V6,
GetQueuedCompletionStatusEx
包含一个可更改选项如果在线程上执行 APC,这将导致它返回。 因此,请使用QueueUserAPC
对无操作 APC 进行排队 1 当您需要特定线程执行其他工作时。 当然,您将需要一些线程安全队列来为中断的线程提供取消内容的指令。如果需要早期版本的兼容性,那么事情就会变得更加困难。 可能性:
使用
GetQueuedCompletionStatus
](http:// msdn.microsoft.com/library/aa364986) 定期返回以检查取消情况。或者,可能更实际,将线程池分为两组。 发起和取消IO的线程。 其余时间,这些线程等待收到执行这些操作之一的信号。 池的另一部分使用 GetQueuedCompletionStatus 等待 IO 完成。
这些都不是那么好,但这始终是旧版本的问题:它们缺乏功能。
1 使用无操作 APC,而不是在 APC 中执行工作,这样就可以绕过 APC 中可以执行的操作的限制及其固有的并发问题。 (由于 APC 是在线程上执行的,因此线程持有的任何锁都保留在 APC 中,任何受保护的状态都将任意不一致。)
1 and 2 are easy, just use the IO Completion port.
But, as you have found 3 requires (prior to Windows V61) the same thread.
If using Windows >= V6,
GetQueuedCompletionStatusEx
includes an alterable option which will cause it to return is an APC is performed on the thread. So useQueueUserAPC
to queue a no-op APC1 when you need that specific thread to do some other work. You will of course need some thread safe queue to provide the interrupted thread with instructions of what to cancel.If earlier version compatibility is required then things get more difficult. Possibilities:
Use the timeout parameter of
GetQueuedCompletionStatus
](http://msdn.microsoft.com/library/aa364986) to return regularly to check for cancellations.Or, possibly more practically, divide the thread pool into two groups. Threads that initiate and cancel IO. The rest of the time these threads spend waiting to be signalled to perform one of these actions. The other part of the pool waits on IO completions with
GetQueuedCompletionStatus
.Neither of these is as nice, but that's always the problem with older versions: they lack functionality.
1 Use a no-op APC rather than doing work in the APC so the limitations on what can be done in an APC and its inherant issues with concurrency are bypassed. (Since an APC is executed on a thread, any locks that thread hold are held in the APC, any state protected will be arbitrarily inconsistent.)