我有一个通过串口生成消息的设备。 当我重新启动设备时,IO完成端口停止读取字节。
代码是调用GetQueuedCompletionStatus():
BOOL bRet = GetQueuedCompletionStatus( m_hCompletionPort, &dwBytesTransferred, &dwCompletionKey, &pOverlapped, INFINITE);
PortMon看起来像:
... IRP_MJ_WRITE Serial1 SUCCESS LENGTH: 7 REBOOT. IRP_MJ_READ Serial1 CANCELLED LENGTH: 1
logging显示以下结果:
bRet=true, dwBytesTransferred=7, pOverlapped=0x0202B028, GetLastError()=997 (sleep forever)
有什么方法可以检测到这种故障并重新build立通信?
我可以监视热量节拍并closures/重新打开串口,但是Windows API允许串口通信像这样静静地下降,这似乎不正确。
如果在打开的串行端口的句柄上执行WaitForSingleObject
以开始读取数据,那么在重新启动设备时是否会显示句柄? 也许这是一种告诉你什么时候需要再次打开端口的方法?
IO完成端口可以毫无问题地处理这种情况。 您不需要关闭并重新打开设备。
在这种情况下最可能的问题是,你有一个线路上的错误(由设备重置),你还没有清除使用ClearCommError()。
您需要预先为您的设备适当地使用SetCommState()和SetCommTimeouts()。 在传递给SetCommState()的DCB中,您需要设置fAbortOnError。 如果你做出列错误,你需要调用ClearCommError(),然后再次读取。
RE:janm(我似乎无法添加评论给你的答案抱歉)
我尝试设置各种标志,包括DCB的fAbortOnError,但GetQueuedCompletionStatus()仍然会无限等待。 我也尝试周期性的超时调用,并检查串行端口的错误。 串口一直很好,但断开连接仍会永久破坏IO完成端口。 设备重新启动可能会创建一个瞬态错误状态…我可能说,因为我从来没有能够检测到它!
一位开发人员也对这个问题有了一个解决办法,也是失败了。 所以我们只是重写代码来使用重叠的串口读取,现在它工作正常。
可能有些东西,我们错过了…最后,我们浪费了更多的时间来解决这个谜,而不是重写代码。