CancelIo()应该取消与调用线程关联的所有待处理 I / O操作。根据我的经验,CancelIo()有时会取消未来 I / O操作。给出:
ReadFile(port, buffer, length, &bytesTransferred, overlapped);
CancelIo(port)
,GetQueuedCompletionStatus()
将永久阻止,永远不会接收读取操作。CancelIo(port)
,GetQueuedCompletionStatus()
将返回0 GetLastError()==ERROR_OPERATION_ABORTED
CancelIo(port)
并且没有待处理或后续读取,GetQueuedCompletionStatus()
将永久阻止。这里的关键点是没有办法检测CancelIo()
何时完成执行。如何确保CancelIo()
已完成执行,并且可以安全地发出进一步的读取请求?
PS:看http://osdir.com/ml/lib.boost.asio.user/2008-02/msg00074.html和http://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/using.html听起来像CancelIo()并不真正可用。客户必须要求Windows XP支持。我有什么选择?
注意:我正在从串口读取。
答案 0 :(得分:3)
CancelIo()
运行正常。我误解了我的代码。
经过进一步调查后发现,代码正在调用CancelIo()
,然后ReadFile()
调用超时INFINITE
。完成端口从未收到读取通知,因为远程端从未发送任何内容。换句话说,CancelIo()
没有取消后续操作。
我找到了一些引人注目的文档here:
编码异步I / O时要小心,因为如果需要,系统保留使操作同步的权利。因此,最好是编写程序以正确处理可以同步或异步完成的I / O操作。示例代码证明了这一点。
事实证明,如果正在读取的数据已被设备驱动程序缓存,则设备驱动程序可以选择以同步方式处理异步操作。经过进一步调查,我发现在CancelIo()
之前调用ReadFile()
时,有时会导致后者同步返回。我不知道为什么完成端口在ReadFile()
之后从未收到CancelIo()
的通知,但我无法再重现此问题。
无论ReadFile()
是同步还是异步,都会发信号通知完成端口。
答案 1 :(得分:2)
等待(可能没有超时)overlapped.Handle
。将设置操作是完成还是取消。
答案 2 :(得分:-1)
可以在没有CancelIo功能的情况下编写异步I / O代码。问题取决于您使用CancelIO的方案。假设您需要实现文件读取线程。线程伪代码:
for(;;) { ReadFile(port, buffer, length, &bytesTransferred, overlapped); WaitForMultipleObjects( overlapped event + stop event); if ( stop event is signaled ) break; if (overlapped event is signaled ) handle ReadFile results }
这样的线程使用重叠的I / O读取文件(套接字,端口等)。大多数时候它在WiatForMultipleObjects行上等待。它在新数据可用时唤醒,或者发出停止事件信号。要停止此线程,请从另一个线程设置stop事件。不使用CancelIO。
答案 3 :(得分:-1)
如果您已经在使用重叠操作,为什么还需要取消I / O? “取消”正在进行的I / O操作的整个概念真的容易出现竞争,并且完全取决于您尝试写入的底层设备堆栈;真正唯一一次你想要这样做是为了解锁正在等待完成I / O的另一个线程。