如何正确地从.NET中的SerialPort读取

Ed *_* S. 3 c# io serial-port

我很尴尬不得不问这样一个问题,但我很难搞清楚如何通过.NET SerialPort类在串口上可靠地读取数据.

我的第一个方法:

static void Main(string[] args)
{
    _port = new SerialPort
    {
        PortName = portName,
        BaudRate = 57600,
        DataBits = 8,
        Parity = Parity.None,
        StopBits = StopBits.One,
        RtsEnable = true,
        DtrEnable = false,
        WriteBufferSize = 2048,
        ReadBufferSize = 2048,
        ReceivedBytesThreshold = 1,
        ReadTimeout = 5000,
    };    

    _port.DataReceived += _port_DataReceived;
    _port.Open();

    // whatever
}

private void _port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{           
    var buf = new byte[_port.BytesToRead];
    var bytesRead = _port.Read(buf, 0, buf.Length);

    _port.DiscardInBuffer();
    for (int i = 0; i < bytesRead; ++i)
    {
        // read each byte, look for start/end values, 
        // signal complete packet event if/when end is found
    }
}
Run Code Online (Sandbox Code Playgroud)

所以这有一个明显的问题; 我正在调用DiscardInBuffer,所以在事件被触发后进入的任何数据都被丢弃,即我正在丢弃数据.

现在,SerialPort.Read()的文档甚至没有声明它是否提前了当前位置的流(真的吗?),但我发现其他来源声称它确实(这是有道理的).但是,如果我不调用DiscardInBuffer我最终会收到RXOver错误,即我花了太长时间处理每条消息并且缓冲区溢出.

所以...我真的不喜欢这个界面.如果我必须在一个单独的线程上处理每个缓冲区,我会这样做,但是它带有一系列问题,我希望我错过了一些东西,因为我对这个界面没有多少经验.

Ben*_*igt 8

Jason提出了一些关于减少来自工作线程的UI访问的好点,但更好的选择是首先不在工作线程上接收数据.

用于port.BaseStream.ReadAsync在您想要的线程上获取事件驱动的数据.我在http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport上写了更多关于这种方法的文章.