问题描述
在 VB.NET 中,使用 SerialPort.ReadLine() 方法与使用 DataReceived 事件处理程序有什么区别?目前,我正在使用数据接收事件处理程序并检测行尾.问题是数据以块的形式出现,而不是 1 行句子.如果我使用 SerialPort.ReadLine() 方法,则数据包含 1 行句子.然而,使用这种方法,有 NewLine 变量来设置端口的行结束字符.readline 方法是否只是为我处理缓冲区?无论使用何种方法,数据是否仍以块的形式出现?
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?
方法一:
While _continue
Try
Dim message As String = _serialPort.ReadLine()
Console.WriteLine(message)
Catch generatedExceptionName As TimeoutException
End Try
End While
方法二:
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,因为它看起来更安全,看起来更漂亮,但有什么意义呢?谢谢
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
推荐答案
在使用 .NET SerialPort 实现时,您应该不要尝试从串口读取使用 DataReceived 事件和任何其他方法.ReadExisting
和 ReadLine
都使用相同的底层 MemoryStream.当事件中断导致您尝试读取已从流中删除的数据时,您将遇到从 ReadLine 中拉出 MemoryStream 数据的情况.
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 关于 ReadLine
阻塞您的 UI 线程是正确的.您有两种方法:使用 DataReceived
事件;或将处理 SerialPort
的代码放在单独的线程上.
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.
使用 DataReceived
事件通常更可取,因为 .NET 会自动在工作线程上运行该事件.但是,您会失去 ReadLine
的免费赠品.如果您需要执行预读(为您提供类似 ReadLine 功能),您必须手动缓冲输入.
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).
这篇关于.Net SerialPort Readline 与 DataReceived 事件处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!