Deadlock issue on closing SerialPort

NETCF V2's SerialPort implementation provides four public events for developers. They can add custom event handlers to handle these events. Since these event handlers are executed by ThreadPool threads, if the developer wants to update form fields with the received data, he/she would need to invoke the associated methods on the form to ask the GUI thread owning the control to update itself.

The correct way to invoke the control update function is to use Control.BeginInvoke() instead of Control.Invoke(). This is because the serial port base stream is locked while serial port events are handled. If the serial port is closed (SerialPort.Close() called) with the GUI thread while the events are being handled (e.g. the user clicked a button to close the serial port, or the user exits the application), the serial port, as part of the port closing process, will attempt to acquire the lock on the base serial stream, and will wait until the lock is acquired. Therefore, the data event handler which has the lock will wait on the Control.Invoke() call for access to the GUI thread indefinitely, and the GUI thread will wait on the SerialPort.Close() call for access to the lock indefinitely. This causes a deadlock on the application, and the user will likely require a reset on the device to be able to rerun the application.

To prevent the issue, simply replace calls that might block for a long time on the serial port event handlers with non-blocking versions of the calls like Control.BeginInvoke().

This suggestion applies to the SerialPort implementation in both the compact and desktop versions of the .NET framework V2.

This posting is provided "AS IS" with no warranties, and confers no rights.

Skip to main content