我正在与一个嵌入式设备进行通信,该设备定期关闭其USB串口仿真,使用USB端口进行其他操作,然后重新启动其串口仿真。在这段短时间内,串行端口从windows设备管理器和注册表中消失,然后在两个位置重新出现。
我的.net 4.5应用程序可以很好地处理这个问题,只要在它发生时我与串口断开连接:在重新启动串口仿真之后,我可以像往常一样重新连接和通信。
但是,如果在设备下降时连接到虚拟串口,然后重新启动其串口仿真,则我的程序不会挂起,但无法访问重新启动的端口。
在这种情况下,windows设备管理器正确地显示端口消失和重新出现,而注册表显示端口消失但永远不会再次出现。当然,这意味着SerialPort.GetPortNames()随后找不到端口,当然,如果我试图关闭已经消失的端口,我将得到一个IOException。
编辑:--我不使用工作线程,我使用的是BaseStream.ReadAsync,我能够捕获IOException并释放原始端口对象。
如前所述,重新启动的模拟端口在设备管理器中显示得很好,但没有显示在HKLM/Hardware/DeviceMap/SerialComm的注册表中。
一旦我在.net中释放(甚至试图关闭)端口,如果我随后强制嵌入式设备重新启动,那么模拟的端口将重新出现在注册表中,并且我可以重新连接到它。不幸的是,这需要与设备进行物理交互,这通常是不可能的。
我正在寻找以编程方式恢复的方法,因为我通常无法访问设备来强制重新启动。
我想,在我释放我的串行端口对象之后,可能有一些方法可以让Windows刷新注册表,但我一直无法找到任何线索来说明如何完成这一任务。
我发现了很多类似于我的问题,但没有一个问题和我的问题完全一样,也没有一个问题给出了答案。
汉斯·帕桑特建议在USB电缆上放置一个标签,邀请人们在几次内拔掉插头,然后把它接回去,看看会发生什么。我喜欢这种想法,但在我的例子中,模拟是由一个嵌入式设备停止并启动的--而且由于硬件的设计,这种行为是必需的。
我试图盲目地将<legacyUnhandledExceptionPolicy enabled="1"/>
添加到我的app.exe.config文件中,但它似乎什么也没做。
基于对类似问题的回答,我尝试将调用Close()移动到单独的线程,并尝试使用异步等待调用关闭。该方法以系统反射错误结束我的应用程序。
当端口消失并重新出现时,如何使应用程序释放其连接(或其他方式),以便正确刷新注册表以匹配设备管理器?
或者,在不终止和重新启动应用程序的情况下,我还能做些什么来从模拟串口的瞬间丢失中恢复吗?
发布于 2016-06-12 18:44:28
框架System.IO.Ports.SerialPort
类当然不会让这件事变得容易。
您需要一些p/ some或C++/CLI来获取断开连接和重新连接的事件.RegisterDeviceNotification
函数是关键。
在此之后,您应该避免使用辅助线程,因为当设备消失或端口被释放时,System.IO.Ports.SerialPort
将抛出异常,并且您将没有机会在完成端口工作线程上安装正确的异常处理程序。
如果您取消了DataReceived
事件,而是将port.BaseStream.ReadAsync
用于事件驱动的重叠接收,则可以在ReadAsync
调用周围放置一个try/catch,并能够通过配置旧端口对象来恢复。额外的好处是,传入的数据随后通过主线程上的同步上下文传递,这样您就不必担心线程同步了。
https://stackoverflow.com/questions/37777626
复制相似问题