我的USB条形码扫描仪有点问题 . 我正在使用带有“SerialPort”类的Scanner:
this._barcodeScanner = new SerialPort(comPort, 9600, Parity.None, 8, StopBits.One) { Handshake = Handshake.None, ReadTimeout = 500, WriteTimeout = 500 };
this._barcodeScanner.Open();
this._barcodeScanner.DataReceived += BarcodeScannerCallback;
如果我通过“SerialPort”类打开USB设备,我就无法正常关闭软件,虚拟端口永远保持打开状态,或直到我重启整个计算机 .
所以我的问题是,在我通过C#代码拔出设备后,有没有办法关闭虚拟端口?
问候
[编辑#1]
好的,还有一些代码:
这样,如果设备已插入,我每隔10秒检查一次:
private bool CheckUsbDeviceAvailability()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\WMI",
"SELECT * FROM MSSerial_PortName WHERE PortName = '" + this.PortName + "'");
if (searcher.Get().Count > 0)
return true;
return false;
}
那是串口的Callback-Event:
void BarcodeScannerCallback(object sender, SerialDataReceivedEventArgs e)
{
Thread.Sleep(500);
string data = this._barcodeScanner.ReadExisting().Replace(Convert.ToChar(2), Convert.ToChar(32)).Trim();
if (data.StartsWith("AX"))
{
string[] arrData = data.Split('\n');
this._barcodeScanner.StopAvailabilityThread();
Barcode code = new Barcode(arrData[0].Replace("\r", ""));
if (CheckIfBarcodeExists(code))
this.UpdateBarcodeNode(code);
else
this.CreateBarcodeNode(code);
BarcodeScannerCallbackEvent(sender, e, code);
this._barcodeScanner.StartAvailabilityThread();
}
this._barcodeScanner.ComDevicePluggedIn = ScannerDevice.ComAvailabilityState.Available;
}
如果它不再回答它将触发“DeviceNotAvailableEvent()”:
void BarcodeScannerDeviceNotAvailableEvent()
{
this._barcodeScanner.Close();
this._barcodeScanner.Dispose();
}
我已经覆盖了“SerialPort”类的Dispose事件,以便它将中止Thread:
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
this._deviceAvailableThread.Abort();
}
base.Dispose(isDisposing);
}
2 回答
这个问题存在于.Net 2,3,3.5中你可以使用框架4(.net 4中不存在问题)
串行端口可以追溯到计算的石器时代 . 这就是你插入ASR-33电传打字机开始输入你的Fortran程序的地方 . 电气接口非常简单 . Windows API也是使用您自己的代码中的串行端口 . 几乎任何运行时环境都支持它们 .
USB完全取代了串口硬件 . 它具有更高级的机器逻辑接口,支持许多不同类型的设备 . 它支持即插即用,允许操作系统检测设备何时连接或移除,以及自动安装设备驱动程序等 .
然而,这种灵活性是有代价的,USB设备总是需要设备驱动程序才能使用 . 设备驱动程序不是平等的 . 不同的驱动程序需要不同的方式来与设备通信 . 通常通过DeviceIoControl()或Read / WriteFile()完成,但这些是非常不透明的API函数 . 在USB的早期,设备制造商将提供一个DLL,它提供了丰富的API来隐藏实现细节 .
这不是很好,制造商不擅长编写好的API,他们肯定不喜欢支持它们 . 因此,一个好的解决方案是支持标准API,可以在任何机器上使用,由任何运行时支持,由其他人记录和维护 . 像串口API一样 .
这不是很好,制造商不擅长编写模拟串行端口的设备驱动程序 . API的最大障碍是它没有逻辑接口来支持它 . 有一些支持用于检测设备是通过DTR硬件握手线连接的,但是没有任何支持来检测端口不再存在 .
拆卸USB设备是个问题 . 在理想情况下,设备驱动程序中内置的仿真器只会假装串口仍在那里,直到设备上的最后一个句柄关闭 . 这将是逻辑实现,因为没有办法触发即插即用事件 . 由于某些奇怪的原因,似乎很难实现 . 大多数USB驱动程序采用简洁的快捷方式,它们只是使设备即使在使用时也会消失 .
这会对使用该设备的任何用户模式代码造成严重破坏 . 这通常被写为假设它是一个真正的串行端口,真正的串行端口不会突然消失 . 至少没有画出明亮的蓝色火花 . 出了什么问题是非常不可预测的,因为它取决于驱动程序如何响应不再存在的设备上的请求 . SerialPort启动的工作线程中的一个无法捕获的异常是一个常见的事故 . 听起来你的驱动程序确实错了,它会在MJ_CLOSE驱动程序请求上生成错误返回代码 . 对于一个驱动程序来说,这是一个合乎逻辑的事情,在所有设备不再存在之后,但是从你的目的来看是无法解决的 . 你有一个手柄,你不能关闭它 . 这是一条没有划桨的小溪 .
.NET的每个主要版本都有一个针对SerialPort类的小补丁,试图尽量减少痛苦 . 但微软可以做的数量有限,捕捉所有错误并假装它们没有发生,最终导致不再提供良好诊断的类,即使有一个好的驱动程序 .
所以实用的方法是:
始终使用Windows中的“安全删除硬盘”托盘图标
使用最新版本的.NET
与供应商联系并要求更新驱动程序
供应糟糕司机的
沟渠供应商
告诉你的用户,因为这是你唯一可以做的事情USB设备,拔掉它不能解决任何问题
使您可以在UI中轻松关闭端口
将USB连接器粘到端口上,因此无法将其移除
第5个子弹也是程序员遇到麻烦的原因 . 编写串口代码并不能诊断出您往往会责怪硬件的软件问题 . 您可以使用硬件做很少的事情但拔下电源插头 . 馊主意 . 现在你有两个问题 .