异步串行端口读取的正确实现

本文关键字:实现 串行端口 读取 异步 | 更新日期: 2023-09-27 18:18:29

我在这里读了一些线程,建议使用port.BaseStream.ReadAsync()与wa_async/await。我不清楚的是,实现这一点的最佳方式是什么?

我仍然使用event_handler,只是使它异步/可等待吗?

private async void myPort_DataReceived(object sender,      SerialDataReceivedEventArgs e)
        {
            byte[] buffer = new byte[myPort.BytesToRead];
            await (myPort.BaseStream.ReadAsync(buffer, 0, buffer.Length));
        }

或者事件处理程序完全忽略,而不是我在循环中调用ReadAsync ?

编辑:一旦解析,我将1)发送数据到TCP服务器和2)写它到sq3lite数据库。

异步串行端口读取的正确实现

微软已经更新了API,允许相对简单的异步读写实现。请注意,您将不会实现同步事件处理程序,这是您所做的,而只是在您希望接收COM端口上的数据时调用此函数:

public async Task<Stream> ReceiveData()
{
    var buffer = new byte[4096];
    int readBytes = 0;
    SerialPort port = new SerialPort(/* ... */);
    using (MemoryStream memoryStream = new MemoryStream())
    {
        while ((readBytes = await port.BaseStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
        {
            memoryStream.Write(buffer, 0, readBytes);
        }
        return memoryStream;
    }
}

这里是另一个替代实现(参见http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport),其中作者解释了SerialPort DataReceived, BytesToRead和其他API成员的问题。他没有使用SerialPort API,因为他指出它的设计、实现和测试都很糟糕,他建议使用BaseStream:

Action kickoffRead = null;
kickoffRead = delegate {
    port.BaseStream.BeginRead(buffer, 0, buffer.Length, delegate (IAsyncResult ar) {
        try {
            int actualLength = port.BaseStream.EndRead(ar);
            byte[] received = new byte[actualLength];
            Buffer.BlockCopy(buffer, 0, received, 0, actualLength);
            raiseAppSerialDataEvent(received);
        }
        catch (IOException exc) {
            handleAppSerialError(exc);
        }
        kickoffRead();
    }, null);
};
kickoffRead();

请注意,我发现使用BCL与BaseStream的性能改进比使用SerialPort API好很多个数量级。