重叠 I/O:如何在完成端口事件或正常事件上唤醒线程? [英] Overlapped I/O: How to wake a thread on a completion port event or a normal event?

查看:21
本文介绍了重叠 I/O:如何在完成端口事件或正常事件上唤醒线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

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

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

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?

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

UPDATE: The solution must run on Windows XP. Unfortunately this rules out using CancelIoEx() or GetQueuedCompletionStatusEx().

推荐答案

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

1 and 2 are easy, just use the IO Completion port.

但是,正如您发现的那样,3 个需要(在 Windows V61 之前)相同的线程.

But, as you have found 3 requires (prior to Windows V61) the same thread.

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

If using Windows >= V6, GetQueuedCompletionStatusEx includes an alterable option which will cause it to return is an APC is performed on the thread. So use QueueUserAPC 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.

或者,可能更实际一些,将线程池分成两组.启动和取消 IO 的线程.其余时间这些线程花在等待收到信号以执行这些操作之一.池的另一部分使用 GetQueuedCompletionStatus 等待 IO 完成.

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 使用无操作 APC 而不是在 APC 中工作,这样可以绕过在 APC 中可以完成的工作的限制及其与并发性的固有问题.(由于APC是在线程上执行的,线程持有的任何锁都持有在APC中,任何受保护的状态都会任意不一致.)

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.)

这篇关于重叠 I/O:如何在完成端口事件或正常事件上唤醒线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆