我有一个通过串口生成消息的设备。当我重启设备时,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
记录显示以下结果:
bRet=true, dwBytesTransferred=7, pOverlapped=0x0202B028, GetLastError()=997
(sleep forever)
有没有办法检测到此故障并重新建立通信?
我可以监控热节拍并关闭/重新打开串口,但是Windows API允许串行通信以这种方式静默丢弃似乎不对。
答案 0 :(得分:1)
如果您为打开的串行端口的句柄执行WaitForSingleObject
以开始读取数据,那么在重启设备时是否会显示句柄信号?也许这是一种告诉您何时需要再次打开端口的方法?
答案 1 :(得分:1)
IO完成端口当然可以毫无问题地处理这种情况。您无需关闭并重新打开设备。
在这种情况下最可能出现的问题是你在线路上有一个错误(由设备复位引起)你还没有使用ClearCommError()清除。
您需要事先为您的设备使用SetCommState()和SetCommTimeouts()。在DCB中传递给SetCommState(),您需要设置fAbortOnError。如果你确实出错了,你需要在重新排列另一个读取之前调用ClearCommError()。
答案 2 :(得分:1)
RE:janm(我似乎无法在你的回答中添加评论抱歉)
我尝试设置各种标志,包括DCB的fAbortOnError,但GetQueuedCompletionStatus()仍会无限期等待。我还尝试定期超时,并检查串口是否有错误。串口总是看起来很好,但断开连接仍会永久性地破坏IO完成端口。设备重启可能会创建一个瞬态错误状态...我可能会说,因为我从来没有能够检测到它!
一位开发人员也对这个问题有所了解,他们也失败了。所以我们只是重写了代码以使用重叠的串口读取,现在它工作正常。
可能有某些东西,我们错过了某个地方......最后,我们浪费了更多的时间来解决这个谜团而不是重写代码。