1
votes

In VB.NET, what is the difference between using the SerialPort.ReadLine() method versus using the DataReceived event handler? Currently, I'm using the data received event handler and detecting the line endings. The problem is the data is coming in chunks and not 1 line sentences. If I use SerialPort.ReadLine() method, the data comes in 1 line sentences. Using this method, however, has the NewLine variable to set the line ending character for the port. Is the readline method just handling the buffer for me? Does the data still come in chunks regardless of the method used?

Method 1:

While _continue
    Try 
        Dim message As String = _serialPort.ReadLine()
        Console.WriteLine(message)
    Catch generatedExceptionName As TimeoutException
    End Try 
End While 

Method 2:

Public Sub StartListener()
    Try

        _serialport = New SerialPort()
        With _serialport
            .PortName = "COM3"
            .BaudRate = 38400
            .DataBits = 8
            .Parity = Parity.None
            .StopBits = StopBits.One
            .Handshake = Handshake.None
            AddHandler .DataReceived, AddressOf DataReceivedHandler
        End With
        _serialport.Open()

    Catch ex As Exception
    End Try
End Sub

Private Shared buffer As String = ""

Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
    Try
        Dim rcv As String = _serialport.ReadExisting()
        buffer = String.Concat(buffer, rcv)

        Dim x As Integer
        Do
            x = buffer.IndexOf(vbCrLf)
            If x > -1 Then
                Console.WriteLine(buffer.Substring(0, x).Trim())
                buffer = buffer.Remove(0, x + 2)
            End If
        Loop Until x = -1
    Catch ex as Exception
    End Try
End Sub

I am currently using Method 2, but was thinking about switching to Method 1 because it seems safer and looks prettier you know, but what's the point? Thanks

2

2 Answers

3
votes

When working with the .NET SerialPort implementation, you should NEVER try to read from the serial port using the DataReceived event and any other method. ReadExisting and ReadLine both use the same underlying MemoryStream. You will run into situations where you are pulling data off the MemoryStream from the ReadLine when the event interrupts causing you to attempt to read data that has already been removed from the stream.

Use one method or the other. Do no use both.

Hans Passant is correct about the ReadLine blocking your UI thread. You have two methods around that: use the DataReceived event; or place your code that handles the SerialPort on a separate thread.

Using the DataReceived event is usually preferable as .NET will run that on a worker thread automatically. You lose the freebie of the ReadLine though. And you have to manually buffer the input if you need to perform read aheads (to give you something like the ReadLine functionality).

3
votes

Your ReadLine() call is synchronous and blocks your code, potentially hanging your program. DataReceived is asynchronous and doesn't. Which makes it harder to use, there is no free lunch. But can be important, serial ports can be slow enough to make your entire program unresponsive to user input. Not usually an issue in a console mode program or when you use a separate thread.

You can call ReadLine() in your DataReceived event handler as well, that's desert. That can technically cause deadlock, you should use the ReadTimeout property.

But since you use the console, there's probably little reason to use DataReceived.