Correct Implementation of Async SerialPort Read

邮差的信 提交于 2019-12-24 05:39:13

问题


I have read a few threads here suggesting to use port.BaseStream.ReadAsync() with waith async / await. What is not clear to me is what is the best way to implement this?

Do i still use the event_handler and just make it 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));
        }

Or is the event handler ignored completely and instead i am calling ReadAsync in a loop?

Edit: Once parsed, I will be 1) Sending the data to a TCP Server and 2) Write it to sq3lite database.


回答1:


Microsoft has updated the API which can allow for a relatively simple async read and write implementation. Please note that you would not implement the synchronous event handler which is what you appear to have done, but simply call this function whenever you expect to receive data on the COM port:

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;
    }
}

Here is another alternative implementation (see http://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport) where the author explains problems with the SerialPort DataReceived, BytesToRead, and other API members. Instead of using the SerialPort API because he indicates it has been poorly designed, implemented and tested he suggests this methodology using the 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();

Please note that the performance improvements I have found using the BCL with BaseStream are many orders of magnitude better than using the SerialPort API.



来源:https://stackoverflow.com/questions/33226414/correct-implementation-of-async-serialport-read

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!