如何等待下一个串口数据追加收集到的字节?

How to wait for next serial port data to be append with the collected byte?

我在读串口。但是其中一个响应大于 127,假设长度可以达到 4,294,967,295。正如我目前所面对的,数据长度是 250(这个值是动态的)。

目前到达的数据不完整。它出现在前 100 个,然后是下一个。响应的长度取决于缓冲区本身。

目前,这是我从串口读取响应的方式。

List<byte> serialByte = new List<byte>();
int bufferLen = 0;
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new SerialDataReceivedDelegate(SerialPort_DataReceived_Client), sender, e);
    }
    else
    {
        SerialPort_DataReceived_Client(sender, e);
    }
}
void SerialPort_DataReceived_Client(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    if (!sp.IsOpen) return;
    var buffer = (dynamic)null;
    bool newData = true;
    int BytesToRead = sp.BytesToRead;
    AppendTextBox($"BytesToRead: {BytesToRead}");
    byte[] temp = new byte[BytesToRead];
    sp.Read(temp, 0, BytesToRead);

    bufferLen = TLV.GetExpectedLength(temp);
    AppendTextBox($"Buffer Len: {bufferLen}");

    bool waitFullData = true;
    bool isLenRetrieved = false;
    serialByte.AddRange(temp);
    buffer = new byte[bufferLen];
    buffer = serialByte.ToArray();
    DataReceived_TranslateData(buffer);
}

日志:-

示例内容长度在 127 以下

15:09:32.351167 PM - BytesToRead: 40
15:09:32.361139 PM - Expected Length: 40

样本内容长度在127以上

15:10:12.783806 PM - BytesToRead: 100
15:10:12.815695 PM - Buffer Len: 271

如果bufferLen等于serialByte.Count,数据就完成了,我会把byte[]传递给方法DataReceived_TranslateData

我正在尝试执行以下操作,但是,我的 UI 冻结,我知道我的方法是完全错误的。

List<byte> serialByte = new List<byte>();
int bufferLen = 0;
bool waitFullData = true;
bool isLenRetrieved = false;
void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    if (this.InvokeRequired)
    {
        this.Invoke(new SerialDataReceivedDelegate(SerialPort_DataReceived_Client), sender, e);
    }
    else
    {
        SerialPort_DataReceived_Client(sender, e);
    }
}
void SerialPort_DataReceived_Client(object sender, SerialDataReceivedEventArgs e)
{
    SerialPort sp = (SerialPort)sender;
    if (!sp.IsOpen) return;
    var buffer = (dynamic)null;
    bool newData = true;
    int BytesToRead = sp.BytesToRead;
    AppendTextBox($"BytesToRead: {BytesToRead}");
    byte[] temp = new byte[BytesToRead];
    sp.Read(temp, 0, BytesToRead);

    bufferLen = TLV.GetExpectedLength(temp);
    AppendTextBox($"Buffer Len: {bufferLen}");

    while (waitFullData)
    {
        if (!isLenRetrieved)
        {
            bufferLen = TLV.GetExpectedLength(temp);
            isLenRetrieved = true;
            AppendTextBox($"Buffer Len: {bufferLen}");
        }
        if (newData)
        {
            serialByte.AddRange(temp);
            newData = false;
        }

        if (bufferLen == serialByte.Count)
        {
            waitFullData = false;
            break;
        }
        else
        {
            Thread.Sleep(100);
        }
    }
    buffer = new byte[bufferLen];
    buffer = serialByte.ToArray();
    DataReceived_TranslateData(buffer);
}

如何等待下一个串口数据,直到长度与预期长度匹配?

首先,不要使用 this.Invoke 调用整个方法,只需将 UI 更新代码放入其中,就像您的 AppendTextBox 方法一样。

其次,不要在 DataReceived 事件中等待。因为每次串口获取数据都会触发这个事件。 while 循环只是阻止它。

你的代码应该是这样的:

    List<byte> serialByte = new List<byte>();
    int bufferLen = 0;

    private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        SerialPort sp = (SerialPort)sender;
        if (!sp.IsOpen) return;

        //other codes

        int BytesToRead = sp.BytesToRead;
        byte[] temp = new byte[BytesToRead];
        sp.Read(temp, 0, BytesToRead);

        serialByte.AddRange(temp);

        //other codes

        if (serialByte.Count >= bufferLen)
        {
            DataReceived_TranslateData(serialByte.GetRange(0, bufferLen).ToArray());
            //clear the list if you need
        }
    }