在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,因为它看起来更安全,看起来更漂亮,但重点是什么?感谢
答案 0 :(得分:3)
您的ReadLine()调用是同步的并阻止您的代码,可能会挂起您的程序。 DataReceived是异步的,但不是。这使得它更难使用,没有免费的午餐。但可能很重要,串口可能足够慢,使您的整个程序无法响应用户输入。在控制台模式程序中或使用单独的线程时通常不会出现问题。
您也可以在DataReceived事件处理程序中调用ReadLine(),这是沙漠。这可能在技术上导致死锁,您应该使用ReadTimeout属性。
但是,由于您使用控制台,因此可能没有理由使用DataReceived。
答案 1 :(得分:3)
使用.NET SerialPort实现时, NEVER 尝试使用DataReceived事件和任何其他方法从串行端口读取。 ReadExisting
和ReadLine
都使用相同的底层MemoryStream。当事件中断导致您尝试读取已从流中删除的数据时,您将遇到从ReadLine将数据从MemoryStream中拉出的情况。
使用一种方法或另一种方法。不要同时使用它们。
Hans Passant关于阻止你的UI线程的ReadLine
是正确的。你有两种方法:使用DataReceived
事件;或者将处理SerialPort
的代码放在一个单独的线程上。
使用DataReceived
事件通常更可取,因为.NET会自动在工作线程上运行它。你失去了ReadLine
的免费赠品。如果需要执行预读,则必须手动缓冲输入(为了提供类似ReadLine功能的东西)。