与手动方法相比,SerialPort.ReadLine()速度慢吗?

时间:2017-07-05 13:17:20

标签: c# serial-port

我最近实施了一个小程序,它读取来自传感器的数据并将其绘制成图表。

数据以5个字节为单位,大约每500μs(波特率:500000)。大约3000个块组成一个完整的线。因此总传输时间约为1.5秒。

当我看到实时图时,我注意到显示的内容与当前测量的内容之间存在严重的延迟。调查,这一切都归结为:

SerialPort.ReadLine();

比传输线多约0.5秒。因此每行读取大约需要2秒。有趣的是,没有数据丢失,每次读取新行时,数据都会略微落后。这对用户来说非常恼火,所以我不能这样离开。

我已经实现了自己的变体,它显示了大约1.5秒的一致时间,并且没有出现延迟。我并不为我的实现感到自豪(或多或少地轮询BaseStream),我想知道是否有办法加速ReadLine类的SerialPort函数。随着我的实现,我也得到了一些损坏的行,并且还没有找到确切的问题。

我已尝试将ReadTimeout更改为1600,但刚刚生成TimeoutException。虽然数据到了。

对于为什么它很慢或解决方法的任何解释都表示赞赏。

作为旁注:我在一个只有Seri​​alPort.ReadLine()的控制台应用程序上尝试了这个,结果是一样的,所以我排除了影响SerialPort的我自己的应用程序

我不确定这是否相关,但我的实现如下:

LineSplitter lineSplitter = new LineSplitter();
async Task<string> SerialReadLineAsync(SerialPort serialPort)
{
    byte[] buffer = new byte[5];
    string ret = string.Empty;

    while (true)
    {
        try
        {
            int bytesRead = await serialPort.BaseStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false);
            byte[] line = lineSplitter.OnIncomingBinaryBlock(this, buffer, bytesRead);
            if (null != line)
            {
                return Encoding.ASCII.GetString(line).TrimEnd('\r', '\n');
            }
        }
        catch
        {
            return string.Empty;
        }
    }
}

LineSplitter如下:

class LineSplitter
{
    // based on: http://www.sparxeng.com/blog/software/reading-lines-serial-port
    public byte Delimiter = (byte)'\n';
    byte[] leftover;


    public byte[] OnIncomingBinaryBlock(object sender, byte[] buffer, int bytesInBuffer)
    {
        leftover = ConcatArray(leftover, buffer, 0, bytesInBuffer);
        int newLineIndex = Array.IndexOf(leftover, Delimiter);
        if (newLineIndex >= 0)
        {
            byte[] result = new byte[newLineIndex+1];
            Array.Copy(leftover, result, result.Length);
            byte[] newLeftover = new byte[leftover.Length - result.Length];
            Array.Copy(leftover, newLineIndex + 1, newLeftover, 0, newLeftover.Length);
            leftover = newLeftover;

            return result;
        }
        return null;
    }

    static byte[] ConcatArray(byte[] head, byte[] tail, int tailOffset, int tailCount)
    {
        byte[] result;
        if (head == null)
        {
            result = new byte[tailCount];
            Array.Copy(tail, tailOffset, result, 0, tailCount);
        }
        else
        {
            result = new byte[head.Length + tailCount];
            head.CopyTo(result, 0);
            Array.Copy(tail, tailOffset, result, head.Length, tailCount);
        }

        return result;
    }
}

1 个答案:

答案 0 :(得分:-1)

我在2008年遇到了与GPS模块交谈的问题。基本上阻塞功能是片状的,解决方案是使用APM。

以下是另一个Stack Overflow答案中的血腥细节:How to do robust SerialPort programming with .NET / C#?

您可能也会感兴趣:How to kill off a pending APM operation