.Net SerialPort Readline与DataReceived事件处理程序

时间:2014-02-10 22:00:10

标签: .net vb.net serial-port

在VB.NET中,使用SerialPort.ReadLine()方法与使用DataReceived事件处理程序有什么区别?目前,我正在使用数据接收事件处理程序并检测行结尾。问题是数据是以块为单位而不是1行句子。如果我使用SerialPort.ReadLine()方法,则数据以1行句子出现。但是,使用此方法的NewLine变量可以设置端口的行结束字符。 readline方法只是为我处理缓冲区吗?无论使用何种方法,数据是否仍然存在?

方法1:

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

方法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

我目前正在使用方法2,但考虑切换到方法1,因为它看起来更安全,看起来更漂亮,但重点是什么?感谢

2 个答案:

答案 0 :(得分:3)

您的ReadLine()调用是同步的并阻止您的代码,可能会挂起您的程序。 DataReceived是异步的,但不是。这使得它更难使用,没有免费的午餐。但可能很重要,串口可能足够慢,使您的整个程序无法响应用户输入。在控制台模式程序中或使用单独的线程时通常不会出现问题。

您也可以在DataReceived事件处理程序中调用ReadLine(),这是沙漠。这可能在技术上导致死锁,您应该使用ReadTimeout属性。

但是,由于您使用控制台,因此可能没有理由使用DataReceived。

答案 1 :(得分:3)

使用.NET SerialPort实现时, NEVER 尝试使用DataReceived事件和任何其他方法从串行端口读取。 ReadExistingReadLine都使用相同的底层MemoryStream。当事件中断导致您尝试读取已从流中删除的数据时,您将遇到从ReadLine将数据从MemoryStream中拉出的情况。

使用一种方法或另一种方法。不要同时使用它们。

Hans Passant关于阻止你的UI线程的ReadLine是正确的。你有两种方法:使用DataReceived事件;或者将处理SerialPort的代码放在一个单独的线程上。

使用DataReceived事件通常更可取,因为.NET会自动在工作线程上运行它。你失去了ReadLine的免费赠品。如果需要执行预读,则必须手动缓冲输入(为了提供类似ReadLine功能的东西)。