使用LibUsbDotNet时,当关闭后再打开USB设备就会报“已关闭safe handle”

由于项目中需要和USB设备通讯,于是用到LibUsbDotNet.dll这个开源的项目。但是在使用的时候发现关闭USB设备后再打开,过2秒就会出现异常“已关闭safe handle”,由于网上关于LibUsbDotNet的资料比较少,查了好久都查不出原因。不过用关键字“已关闭safe handle”的时候,发现很多人使用SerialPort时也遇到这个问题。

由于对底层实现不懂,所以只能猜测原因。在使用Usb.read()或者SerialPort.read()方法的时候,都会开辟一个局部变量数组用来保存读取的数据,然后将这个数组引用作为参数传入方法。这些方法是线程阻塞的,但是只是表面上的阻塞,底层可能保存着数组的句柄,并且一直尝试读取数据并转移到数组。这样如果中止线程的话,C#的垃圾回收机制会回收到线程的数组,而这时候设备没有关闭,read()方法仍然在尝试将数据转移到已经被释放的数组中。这时候如果来数据了,就会报“已关闭safe handle”。
而大部分人在使用Usb或者SerialPort通讯时,都会开出一个线程,线程中申请数组然后循环往数组中读取数据。而在关闭设备的时候,都会先去中止读取线程,然后再关闭设备。这样一来就中招了。。。

解决的办法很简单,两个方法:1、使用全局数组变量作为参数传入到方法中。这样在中止线程的时候不会回收。2、先关闭设备,再中止线程。

当然了,这一切都是猜测,不过使用了这两个方法之后,就没有错误了。。。可能是猜中原因了?

一直报错时的代码:

 1 /// <summary>
 2         /// 关闭USB设备
 3         /// </summary>
 4         public static void closeDevice()
 5         {
 6             //停止监听线程
 7             EndListenThread();
 8             //停止读线程
 9             try
10             {
11                 ReadThread.Abort();
12             }
13             catch
14             { }
15             finally
16             {
17                 ReadThread = null;
18             }
19 
20             if (!ReferenceEquals(usbDevice, null))
21                 usbDevice.Close();
22             if (!ReferenceEquals(usbReader, null))
23                 usbReader.Dispose();
24             if (!ReferenceEquals(usbWriter, null))
25                 usbWriter.Dispose();
26             
27             GlobalStatus.Devicestatus = false;
28             Console.WriteLine("关闭设备!");
29 
30             //USB关闭事件通知
31             if (UsbDeviceChanged != null)
32             {
33                 UsbDeviceChanged("UsbNotice", new UsbConnectionEventArgs(0, false));
34             }
35         }

只是将设备关闭的位置换了一下,困扰我很长时间的问题就消失了。。。

 1 /// <summary>
 2         /// 关闭USB设备
 3         /// </summary>
 4         public static void closeDevice()
 5         {
 6             if (!ReferenceEquals(usbDevice, null))
 7                 usbDevice.Close();
 8             if (!ReferenceEquals(usbReader, null))
 9                 usbReader.Dispose();
10             if (!ReferenceEquals(usbWriter, null))
11                 usbWriter.Dispose();
12             
13             //停止监听线程
14             EndListenThread();
15             //停止读线程
16             try
17             {
18                 ReadThread.Abort();
19             }
20             catch
21             { }
22             finally
23             {
24                 ReadThread = null;
25             }
26 
27             GlobalStatus.Devicestatus = false;
28             Console.WriteLine("关闭设备!");
29 
30             //USB关闭事件通知
31             if (UsbDeviceChanged != null)
32             {
33                 UsbDeviceChanged("UsbNotice", new UsbConnectionEventArgs(0, false));
34             }
35         }

 

使用LibUsbDotNet时,当关闭后再打开USB设备就会报“已关闭safe handle”,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。