views:

84

answers:

5

This is a major issue - I use a serial port in an application here and I poll the status of the attached device by opening and then closing the port again.

If the device fails, SOMETIMES the SerialPort.Close() - method NEVER returns and this is really a show stopper.

The worst thing is that even shutting down the application using the taskmanager fails, it doesn't work (or it is forbidden, by chance).

The attached device is a POS printer (USB) which simulates COM3, it's an Epson TM-T88IV (a very good model, btw).

Does anyone of you have experience with that?

+1  A: 

What about using BackGround thread to poll the device so that it does not stop your application from exiting?

Giorgi
Worth trying, but it probably won't work. If taskmanager can't stop the process, I don't think the CLR will be able to. Just guessing though.
MusiGenesis
+1  A: 

Here's a link with lots of other links to this problem and (potential) solutions:

http://www.vbforums.com/showthread.php?t=558000

MusiGenesis
+2  A: 

Prior to .Net 4.0 a lot could go wrong with USB to SerialPort devices(crash program/system, etc.). It was easy to test the errors by pulling the USB adapter with the port active.

Recently I ran some tests using .Net 4.0 and it is fixed(certainly improved)??? The test was a simple RX / TX through a USB SerialPort with a loopback, and pull the USB adapter while in use. My program did not crash, and I was able to re-open the port! This is a major improvement.

dbasnett
+3  A: 

Repeatedly opening and closing the port is not recommended. Check the Remarks section in the MSDN Library article for SerialPort.Close(). There's a background thread that needs to shut down before a port can be opened again, that takes time. The amount of time is not predictable.

The Close() method can easily deadlock if the DataReceived event handler is currently running. The most typical way to get the deadlock is calling Control.Invoke() in the event handler. Make sure you don't use any code in the event handler that blocks or requires a thread context switch. Using BeginInvoke() is fine.

Not being able to kill the program is caused by a problem in the serial port device driver. Start Taskmgr.exe, Process tab, View + Select Columns and tick "Handles". If after killing the program, you see the Handles column showing 1 then the serial port driver is hanging on to an I/O request that it doesn't complete. The process cannot terminate until all its kernel mode threads are exited.

There's little you can do about that particular problem, other than hoping for a driver update or switching to another vendor. Especially USB serial port emulators are notorious for having lousy device drivers. You get rid of a troublemaker like that by taking it out the parking lot and running it over with your car several times.

Another typical problem with USB emulators is that they are so easy to disconnect while they are in use. That works about as well as jerking a flash drive out of the socket while Windows is writing to it. It would also be a good way to get the device driver hung .NET versions prior to version 4.0 suffer from a heart attack in a background thread when the device suddenly disappears. Short from upgrading, a small sign next to the connector that says "Do not disconnect while in use!" is a practical workaround. They will anyway but get bored with it after a couple of times.

Hans Passant
+1 for the parking lot comment.
MusiGenesis
+2  A: 

While it is sometimes a problem that the SerialPort.Close method deadlocks, that should not prevent Task Manager from killing your process. If you can't kill your process, this is almost certainly due to a bug in the USB serial driver. Unfortunately, your options are most likely these:

  • don't poll for device status
  • get the vendor to fix the bug
  • work around the problem by figuring out a way to poll the device status without accessing the serial port
  • work around the problem by accessing the device via some other method (perhaps direct USB manipulation)
Gabe