我想使用线程池来启动/取消重叠读取操作——分别使用 ReadFile()
和 CancelIo()
——以及处理任何读取操作完成时的完成端口事件。
- 任何线程都可以发起读操作
- 任何线程都可以处理读取完成事件
- 只有发起读取的线程可以取消它(这是一个
CancelIo()
限制)
我不确定如何实现它。通常调用 GetQueuedCompletionStatus()
来等待完成端口事件,调用 WaitForSingleObject()
来等待正常事件,但不清楚如何混合使用这两者。如果 PostQueuedCompletionStatus()
让我指定一个特定的线程来唤醒我就会被设置。有什么想法吗?
更新:该解决方案必须在 Windows XP 上运行。不幸的是,这排除了使用 CancelIoEx()
或 GetQueuedCompletionStatusEx()
的可能性。
最佳答案
1和2很简单,只需要使用IO Completion端口即可。
但是,正如您发现的那样,3 需要(在 Windows V61 之前)相同的线程。
如果使用 Windows >= V6,GetQueuedCompletionStatusEx
包括一个可变选项,如果在线程上执行 APC,它将导致它返回。所以使用 QueueUserAPC
当您需要特定线程执行其他工作时,将无操作 APC1 排队。您当然需要一些线程安全队列来为被中断的线程提供要取消的指令。
如果需要早期版本兼容性,那么事情就会变得更加困难。可能性:
使用
GetQueuedCompletionStatus
]( http://msdn.microsoft.com/library/aa364986 )的超时参数定期返回检查取消。或者,更实际的做法是,将线程池分成两组。发起和取消 IO 的线程。其余时间这些线程花在等待收到执行这些操作之一的信号上。池的另一部分使用
GetQueuedCompletionStatus
等待 IO 完成。
这些都不是很好,但这始终是旧版本的问题:它们缺乏功能。
1 使用无操作 APC 而不是在 APC 中工作,这样可以绕过 APC 中可以完成的操作的限制及其固有的并发问题。 (由于 APC 是在线程上执行的,线程持有的任何锁都在 APC 中持有,任何 protected 状态都将是任意不一致的。)
关于windows - 重叠 I/O : How to wake a thread on a completion port event or a normal event?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/961343/