C# - SerialPort.read() 速度问题

C# - SerialPort.read() speed issue

我的代码旨在从串行设备获取数据并将其内容打印到 MS Forms 应用程序。我使用的 IDE 是 Visual Studio 2019 - 社区。

设备确实发送了可变大小的数据包。首先,我必须解码数据包“header”以获得进一步处理的关键信息,即第一个数据包通道和数据包长度。

由于数据包既不包含行结束符,也没有结尾处的固定字符,因此函数SerialPort.ReadTo()SerialPort.ReadLine() 没有用。因此只能使用SerialPort.Read(buf,offset,count)

由于发送相当大的数据包(512 字节)确实需要时间,我实现了一个计算所需等待时间的函数,定义为 (1000ms/baud-rate*(8*byte-count))+100ms

在测试时,我遇到了延迟,远远超过了预期的等待时间,因此为函数的不同部分实现了一个测量函数。

在正常情况下(有期望的等待时间)我除了日志到控制台是这样的: Load Header(+122ms) Load Data (+326ms) Transform (+3ms)

但它只适用于一些可变数量的记录,通常是 10,之后,执行时间会更糟:

Load Header(+972ms) Load Data (+990ms) Transform (+2ms)

这里可以看到完整的函数:

private void decodeWriteResponse(int identifier, object sender, SerialDataReceivedEventArgs e)
    {
        /* MEASURE TIME NOW */
        long start = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();

        var serialPort = (SerialPort)sender;                    //new serial port object
        int delay = ComPort.getWaitTime(7);                     //Returns the wait time (1s/baudrate * bytecount *8) +100ms Additional
        Task.Delay(delay).Wait();                               //wait until the device has send all its data!
        byte[] databytes = new byte[6];                          //new buffer
        try
        {
            serialPort.Read(databytes, 0, 6);                    //read the data
        }
        catch (Exception) { };

        /* MEASURE TIME NOW */
        long between_header = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();

        /* Read the Data from Port */
        int rec_len = databytes[1] | databytes[2] << 8;         //Extract number of channels
        int start_chnl = databytes[3] | databytes[4] << 8;      //Extract the first channel

        delay = ComPort.getWaitTime(rec_len+7);                 //get wait time
        Task.Delay(delay).Wait();                               //wait until the device has send all its data!
        byte[] buf = new byte[rec_len-3];                       //new buffer

        try
        {
            serialPort.Read(buf, 0, rec_len-3);                  //read the data
        }
        catch (Exception) {}


        /* MEASURE TIME NOW */
        long after_load = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();

        /* Now perform spectrum analysis */
        decodeSpectrumData(buf, start_chnl, rec_len-4);

       /*MEASURE TIME NOW */
       long end = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
       Form.rtxtDataArea.AppendText("Load Header(+" + (between_header - start).ToString() + "ms) Load Data (+" + (after_load - between_header).ToString() + "ms) Transform (+" + (end - after_load) + "ms)\n");



        /*Update the Write handler */
        loadSpectrumHandler(1);

    }

什么可能导致此问题? 我已经在 Visual Studio 中用“debug”测试过它,并作为“Release”独立测试过,但没有区别。

与其试图计算消息到达端口需要多长时间,为什么不循环读取数据直到你拥有所有数据?例如,读取 header 并计算消息大小。然后读取该字节数。例如:

// See if there are at least enough bytes for a header
if (serialPort.BytesToRead >= 6) {
    byte[] databytes = new byte[6];
    serialPort.Read(databytes, 0, 6);
    // Parse the header - you have to create this function
    int calculatedMsgSize = ValidateHeader(databytes);
    byte [] msg = new byte[calculatedMsgSize];
    int bytesRead = 0;
    while (bytesRead < calculatedMsgSize) {
        if (serialPort.BytesToRead) {
            bytesRead += serialPort.Read(msg, bytesRead,
                Math.min(calculatedMsgSize - bytesRead, serialPort.BytesToRead));
        }
    }
    // You should now have a complete message
    HandleMsg(msg);
}