重叠I / O:如何在完成端口事件或正常事件上唤醒线程?

时间:2009-06-07 06:46:42

标签: windows iocp

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

  1. 任何线程都可以启动读取操作
  2. 任何线程都可以处理读完成事件
  3. 只有发起读取的线程可以取消它(这是CancelIo()限制)
  4. 我不确定如何实现这一点。一个通常调用GetQueuedCompletionStatus()等待完成端口事件,WaitForSingleObject()等待正常事件,但不清楚如何混合两者。如果PostQueuedCompletionStatus()允许我指定要唤醒的特定线程,我将被设置。有什么想法吗?

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

1 个答案:

答案 0 :(得分:3)

1和2很简单,只需使用IO完成端口。

但是,你已经发现3个需要(在Windows V6 1 之前)相同的线程。

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

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

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

  • 或者,可能更实际地,将线程池分成两组。启动和取消IO的线程。其余时间这些线程等待发出信号以执行其中一个操作。池的另一部分使用GetQueuedCompletionStatus等待IO完成。

这些都不是很好,但旧版本总是存在问题:它们缺乏功能。

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