SerialPort and DataReceived Event [Ryan Byington]

I have seen a few customers complain that their DataReceived event handler was never getting called and I thought I would share their problems here so you can learn from their mistakes. The problems revolve around the port not being open. This is sometimes as obvious as not calling SeiralPort.Close if you expect your DataReceived handler to be called but sometimes it is not as obvious as the GC can Close the SerialPort.<?xml:namespace prefix = o />

One customer had something like the following code:

            shared Dim WithEvents mySerialPort as SerialPort

           

            public shared sub SendText(text as string)

                        mySerialPort = new SerialPort("COM1")

                        mySerialPort.Open()

                        mySerialPort.WriteLine(text)

                        mySerialPort.Close()

            end sub

 

            public shared sub MySerialPortDataReceviedHandler( _

                        sender as Object, _

                        e As SerialDataReceivedEventArgs) _

                        Handles mySerialPort.DataReceived

                        'Read here...

            end sub

On the surface this may seem like everything should work. However the DataReceived event handler will not get called if the port has been closed. Also, the handler will only get called for data received since the port has been opened and the MySerialPortDataReceviedHandler is setup to handle the DataReceived event. So in this example the customer’s DataReceived handler will only get called for data received while code is executing between the Open call and the Close call in the SendText method. This is a pretty small window so it is unlikely that the customer would ever see their handler get called. The fix here is to not open and close the port for every write but open the port when the app is starting up and close the port when it is shutting down.

 

Another customer had the following code:

            public static void Main()

            {

                        SerialPort mySerialPort = new SerialPort("COM1");

 

                        mySerialPort.DataReceived += MySerialPortDataReceviedHandler;

                        mySerialPort.Open();

 

                        Console.WriteLine("Press any key to continue...");

                        Console.ReadKey();

            }

 

            private static void MySerialPortDataReceviedHandler(

                        object sender,

                        SerialDataReceivedEventArgs e)

            {

                        //Read here...

            }

 

The problem here is a lot more subtle, the customer opened the port setup MySerialPortDataReceviedHandler to handle the DataReceived event and makes not calls to SerialPort.Close(). However the GC can actually close the port after Open has been called since there are no more references to mySerialPort after this call. An object is eligible to be GC’d as soon as there are no more references to the object. You can read more about this at https://blogs.msdn.com/cbrumme/archive/2003/04/19/51365.aspx. The fix is to make a call to SerialPort.Close() at the very end of the Main method. This keeps the mySerialPort alive until the end of this method.