如何找出CancelIo()何时完成?

时间:2010-10-13 05:51:22

标签: windows iocp cancelio

CancelIo()应该取消与调用线程关联的所有待处理 I / O操作。根据我的经验,CancelIo()有时会取消未来 I / O操作。给出:

ReadFile(port, buffer, length, &bytesTransferred, overlapped);
  1. 如果我在读取之前立即调用CancelIo(port)GetQueuedCompletionStatus()将永久阻止,永远不会接收读取操作。
  2. 如果我在阅读后立即调用CancelIo(port)GetQueuedCompletionStatus()将返回0 GetLastError()==ERROR_OPERATION_ABORTED
  3. 如果我调用CancelIo(port)并且没有待处理或后续读取,GetQueuedCompletionStatus()将永久阻止。
  4. 这里的关键点是没有办法检测CancelIo()何时完成执行。如何确保CancelIo()已完成执行,并且可以安全地发出进一步的读取请求?

    PS:看http://osdir.com/ml/lib.boost.asio.user/2008-02/msg00074.htmlhttp://www.boost.org/doc/libs/1_44_0/doc/html/boost_asio/using.html听起来像CancelIo()并不真正可用。客户必须要求Windows XP支持。我有什么选择?

    注意:我正在从串口读取。

4 个答案:

答案 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的另一个线程。