January 4, 2012

Fixing lock up on SerialPort.Close()


Earlier this year I bought several Arduino boards to do some hardware interfacing and programming. It all worked out pretty well excep the part where the application locks up completely.

The Arduino connects to the computer using USB, but it emulates a serial port, it's really easy to communicate with the Arduino using the standard SerialPort Class in Visual Basic 2008, but the application sometimes locks up when I'm done using the serial port and attempt to close it. A Google search reveals hundreds of other people facing the same issue, and apparently no easy solution. So after some head banging, I found that the trick was to put the SerialPort.Close() method into a thread, and also handle the I/O exception that sometimes happens. See below for code.

Instead of just closing the port, I created a thread:
Dim t As New Thread(AddressOf ClosePort)
t.Start()

And put the actual Close() method into a subroutine:

Public Sub ClosePort ()
    SerialPort1.Close()
End Sub

In the subroutine that handles DataReceived events, I added an exception handler:

Private Sub SerialPort1_DataReceived(ByVal sender As System.Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs)
    On Error Resume Next
    Me.Invoke(New myDelegate(AddressOf updateTextBox), New Object() {})
End Sub

In this example, the subroutine invokes the updateTextBox subroutine, which does a ReadLine on the serial port and sends the captured data to a textbox.

It's obvious by now that because SerialPort.Close() sometimes waits on DataReceived and the UI, so just closing the port when that occurs hangs the application. By putting SerialPort.Close() into a new thread, instead of the application hanging, the DataReceived event started giving exceptions due to the port being closed, so handling the exception fixed that issue. At first I tried removing the event handler, but that only reduced the frequency of the exceptions, but did not completely get rid of it. Using an exception handler was probably best, but also see disclaimer below.

Disclaimer: I'm not a programmer, and this may not be the best way or even the right way to solve the serial port lock up issue, but it works for me.

No comments: