1

我想使用线程池来启动/取消重叠的读取操作——分别使用ReadFile()CancelIo()——以及在读取操作完成时处理任何完成端口事件。

  1. 任何线程都可以发起读操作
  2. 任何线程都可以处理读取完成事件
  3. 只有发起读取的线程可以取消它(这是一个CancelIo()限制)

我不确定如何实现这一点。通常调用GetQueuedCompletionStatus()等待完成端口事件和WaitForSingleObject()等待正常事件,但不清楚如何混合两者。如果PostQueuedCompletionStatus()让我指定要唤醒的特定线程,我会被设置。有任何想法吗?

更新:该解决方案必须在 Windows XP 上运行。不幸的是,这排除了使用CancelIoEx()or GetQueuedCompletionStatusEx()

4

1 回答 1

4

1 和 2 很简单,只需使用 IO Completion 端口即可。

但是,正如您发现 3 需要(在 Windows V6 1之前)相同的线程。

如果使用 Windows >= V6,GetQueuedCompletionStatusEx则包括一个可更改的选项,该选项将导致它返回是在线程上执行 APC。因此,当您需要特定线程执行其他工作时,请使用QueueUserAPC将无操作 APC 1排队。您当然需要一些线程安全队列来为中断的线程提供取消内容的指令。

如果需要早期版本的兼容性,那么事情就会变得更加困难。可能性:

  • 使用GetQueuedCompletionStatus]( http://msdn.microsoft.com/library/aa364986 ) 的超时参数定期返回以检查取消。

  • 或者,可能更实际地,将线程池分为两组。启动和取消 IO 的线程。这些线程花费的其余时间等待被通知执行这些操作之一。池的另一部分等待 IO 完成,使用GetQueuedCompletionStatus.

这些都不是很好,但这始终是旧版本的问题:它们缺乏功能。

1使用无操作 APC 而不是在 APC 中工作,这样可以绕过 APC 中可以完成的操作的限制及其与并发相关的固有问题。(由于 APC 是在线程上执行的,因此线程持有的任何锁都保存在 APC 中,任何受保护的状态都将是任意不一致的。)

于 2009-06-07T10:17:38.023 回答