如何找出何时CancelIo完成?

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支持。 我有什么select?

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

CancelIo()对已经被读取的字节做了什么?

CancelIo()工作正常。 我误解了我的代码。

经过进一步的调查,事实证明代码调用了CancelIo()之后是ReadFile() ,并且超时INFINITE 。 完成端口从来没有得到读取的通知,因为远端没有发送任何东西。 换句话说, CancelIo()并没有取消后续的操作。

我在这里找到一些令人大开眼界的文档:

编码异步I / O时要小心,因为如果需要,系统保留使操作同步的权利 。 因此,最好是编写程序来正确处理可能同步或异步完成的I / O操作。 示例代码演示了这种考虑。

事实证明,如果读取的数据已被设备驱动程序缓存,则设备驱动程序可以选择以同步方式处理异步操作。 经过进一步调查,我发现当在ReadFile()之前调用CancelIo()时,有时会导致后者同步返回。 我不知道为什么完成端口在CancelIo()之后永远不会收到ReadFile()通知,但是我不能再重现这个问题。

无论ReadFile()是同步的还是异步的,完成端口都会发出信号。

等待(可能与零超时) overlapped.Handle 。处理。 它将被设置是否操作完成或取消。

如果您已经在使用重叠操作,为什么您需要取消I / O? “取消”正在进行的I / O操作的整个概念实际上是种族倾向性的,完全取决于您要写入的基础设备堆栈; 真正唯一的一次你想这样做是为了阻止正在等待I / O完成的另一个线程。

可以编写不具有CancelIo功能的异步I / O代码。 问题取决于您使用CancelIO的场景。 假设你需要实现文件读取线程。 线程伪代码:

对于(;;)

{

ReadFile(端口,缓冲区,长度和bytesTransferred,重叠);

WaitForMultipleObjects(重叠事件+停止事件);

如果(停止事件发信号)

打破;

如果(重叠事件被发信号通知)

处理ReadFile结果

}

这样的线程使用重叠的I / O读取文件(套接字,端口等)。 大部分时间在WiatForMultipleObjects行上等待。 新数据可用时唤醒,或停止事件信号。 要停止此线程,请从另一个线程设置停止事件。 不使用CancelIO。

相关文章

引言 本文从Linux小白的视角, 在CentOS 7.x服务器上搭建一个...
引言: 多线程编程/异步编程非常复杂,有很多概念和工具需要...
一. 宏观概念 ASP.NET Core Middleware是在应用程序处理管道...
背景 在.Net和C#中运行异步代码相当简单,因为我们有时候需要...
HTTP基本认证 在HTTP中,HTTP基本认证(Basic Authenticatio...
1.Linq 执行多列排序 OrderBy的意义是按照指定顺序排序,连续...