Preventing .net serialport crashing on FTDI USB device disconnect
I have an application which is supposed to communicate with multiple custom devices, some of which use FTDI USB-to-serial converter chips, and some of which use TCP. The application needs to be able to accept data at any time, from devices which may be plugged or unplugged at any time; the application serves as a bridge between devices and a database.
It seems that when a device is unplugged, it will often cause the SerialPort class to throw an exception in a BackgroundWorker thread and crash the application.
My present remedy, which is probably absurdly complicated, is to have a helper开发者_JAVA百科 application send/receive serial port data and relay it to/from a TCP socket. When my main application sees that a USB device is plugged in, it launches this other application and then uses a TCP socket to communicate with it. If multiple USB devices are plugged in, a separate instance of the helper application will be launched for each. When a USB port is unplugged, the helper application will crash, but the "Unexpected shutdown" message will be stifled.
This approach works, but it seems massively unsatisfying. There's got to be a better way.
I had the same problems with .NET 2.0 and I reverted to using the FTDI dll wrapper: http://www.ftdichip.com/Support/SoftwareExamples/CodeExamples/CSharp/FTD2XX_NET_1010.zip
Works very well, and you have access to control the real goodies of the driver, such as programmatically setting the latency timer.
I wrote my own class to detect unplug events, by catching the FT_IO_ERROR event, when trying to read the data. This is not entirely satisfying, by catching an error and claiming it is an unplug. But it works.
I have been talking to FTDI about this and recently they released a new application note: http://ftdichip.com/Support/Documents/AppNotes/AN_152_Detecting_USB_%20Device_Insertion_and_Removal.pdf
That uses the WM_DEVICECHANGE event to detect USB unplugs. Also works, but there is a small catch. Because it is a window message, it only works if you have a GUI and there are cases where the event will not arrive at your application, if another application is running and catches the event before you can process it.
The final option is to use WMI to do the detection.You can use the ManagementEventWatcher to create a listener on create and delete. Also got this to work, however there were some USB ports on my laptop where the FTDI driver would not give the correct COM port and location ID back (actually, just nothing at all) and that is the info which I could read from WMI, so I could not link a WMI event to the connected device in the DLL wrapper.
I reported this issue to FTDI in june/july 2010 and supposedly the GetCOMportNumber and Location ID issues are fixed in their 2.08.02 driver version (august), but I have not had the time to recheck this.
So far my experiences with the USB hell....
I have tested removing a USB to serial adapter while in use under .Net 4.0. It does not cause application crashes as did previous versions of .Net. Also, under previous versions, not only would the application crash, but sometimes you had to reboot to get the port to work at all.
精彩评论