异步串口读取的正确实现方式

5

我在这里读到了一些帖子,建议使用port.BaseStream.ReadAsync()与waith async / await。但对我来说不清楚的是,实现这个的最佳方法是什么?

我是否仍然使用event_handler并将其设置为async / awaitable?

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数据库。


我们的问题中有一个标签系统,您不需要在标题中添加标签。 - Scott Chamberlain
你能提供关于你问题的更多细节吗?"myPort"是什么?"SerialPort"又是什么? - Xiaomin Wu
1
@XiaominWu SerialPort 是.NET框架中用于与COM端口通信的类。@user1957413,请展示您将如何使用这些数据,除非您解释您试图做什么,否则我们无法告诉您如何操作。请在问题中更新一个不使用async/await的示例,我们将向您展示如何使用异步API。 - Scott Chamberlain
1个回答

5

微软已更新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的、和其他API成员存在的问题。他建议使用BaseStream代替SerialPort API,因为他认为其设计、实现和测试都不好。请参考该方法。
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 快几个数量级。

谢谢,如果您能详细说明第二种解决方案,那将非常有帮助。在找到这个页面之前,我已经看过您提供的链接文章了。但是我并没有真正理解他的解决方案是如何工作的,所以我继续搜索。 此外,这篇文章写于相当长时间之前。原生API在他描述的方面仍然存在缺陷吗? - Curtwagner1984
此外,文章还提到较新的.NET版本在BaseStream类中有readAsync方法。也许使用它们会更好? - Curtwagner1984
感谢更新。我已经不在同一家雇主那里了,所以没有设备进行研究和测试。 - user8128167
我有这个问题,而ReadAsync似乎并没有更好的解决办法。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接