C#Serialport未在一次传输中接收所有字节

C#Serialport未在一次传输中接收所有字节,c#,serial-port,C#,Serial Port,我使用下面的代码通过串行端口接收十六进制数据,当这些传输是同一个传输的一部分时,似乎有些传输被分成两行。如何确保正确接收每个传输 public void Receiver(object sender, SerialDataReceivedEventArgs e) { string data; do { data = COMPort.ReadExisting(); } while (COMPort.BytesToRead != 0); R

我使用下面的代码通过串行端口接收十六进制数据,当这些传输是同一个传输的一部分时,似乎有些传输被分成两行。如何确保正确接收每个传输

public void Receiver(object sender, SerialDataReceivedEventArgs e)
{
    string data;

    do
    {
        data = COMPort.ReadExisting();
    } while (COMPort.BytesToRead != 0);

    RxARR = data.ToCharArray().ToList();
    Dispatcher.Invoke(new MethodInvoker(Display)); // Start "Display" on the UI thread
} 

您永远不应该假设来自串行端口的数据是一次性提供给您的(顺便说一句,网络通信也是如此)。您需要确保您的代码仅在收到所有信息时才接受消息

一切都很难定义。这可以是定义的终止序列(例如
\r\n
EOL
字节)之前的所有字符,也可以是读取固定数量字节之前的所有字符。通常可以说,由于每条消息都可以被分段,没有定义的消息结束信号,就不可能进行可靠的通信

我们所做的是:

  • 创建
    StringBuilder
  • 将所有内容读入
    StringBuilder
  • 搜索终止序列
  • 删除从
    StringBuilder
    到终止序列(包括终止序列)的所有内容
  • 处理那块数据
  • 从3开始重复,直到找不到终止顺序
  • 将剩余字符保留在
    StringBuilder
    中,因为这是新消息的开始
  • 伪代码:

    private StringBuilder serialBuffer = new StringBuilder();
    private string terminationSequence = "\r\n"; // Anything that can't be part of a message
    
    public void Receiver(object sender, SerialDataReceivedEventArgs e)
    {
        string data = COMPort.ReadExisting();
        serialBuffer.Append(data);
    
        string bufferString = serialBuffer.ToString();
    
        int index = -1;
        do
        {
            index = bufferString.IndexOf(terminationSequence);  
            if (index > -1)
            {
                string message = bufferString.Substring(0, index);
                bufferString = bufferString.Remove(0, index + terminationSequence.Length);
    
                HandleMessage(message);
            }
        }
        while (index > -1)
    
        serialBuffer = new StringBuilder(bufferString);
    } 
    


    顺便说一下:不需要在
    DataReceived
    事件中循环,因为每当准备读取新内容时,
    SerialPort
    就会调用此事件。在循环中读取可能会干扰默认情况下的
    SerialPort
    操作。所以:不要在该事件中读取循环!“循环”是由
    SerialPort

    按顺序触发的事件,我的情况几乎相同

    正如托尔斯滕所说,数据有时不会立即出现。。 也许是因为硬件或是小玩意

    真正适合我的是:

            var end = '\r';
            int dataLength = _serialPort.BytesToRead;
            byte[] data = new byte[dataLength];
            int nbrDataRead = _serialPort.Read(data, 0, dataLength);
    
            RxString = Encoding.ASCII.GetString(data);
            txtCod.AppendText(RxString);
    
            if (RxString.IndexOf((char)end) > -1)
            {
                this.Invoke(new EventHandler(Final));   
            } 
    

    在vb.net中,这与什么是等价的?还没有测试,但我相信smth是这样的
    Dim[end]=ControlChars.Cr Dim dataLength As Integer=_serialPort.BytesToRead Dim data As Byte()=New Byte(dataLength-1){}Dim nbrDataRead As Integer=_serialPort.Read(data,0,dataLength)RxString=Encoding.ASCII.GetString(data)txtCod.AppendText(RxString)如果RxString.IndexOf(CChar([end])>-1),则Me.Invoke(New EventHandler(Final))End If
    你能帮我只把这部分转换成dotnet吗?If(RxString.IndexOf((char)End)>-1{this.Invoke(new EventHandler(Final));}@Adib类似这样的东西,
    如果RxString.IndexOf(CChar([End])>-1那么me.Invoke(new EventHandler(Final))End If
    在vb.net中,什么是terminationSequence的等价物?terminationSequence是什么意思?我指的是定义的字节序列,它不属于任何消息的一部分,因此允许您确定消息是否完整。当您遇到该序列时(字节序列)字节,消息结束。@adib在上面的代码中,终止序列只是一个字符串。我将更改我的答案以使其更清楚。如果可能,请您回答这个问题?