C # Async Serial Port Read

I have a class that is read from a serial port using a DataReceived event handler in C #. When I receive the data, I know that the header will contain 5 bytes, so I do not want to do anything with the data as long as I have at least that. My current code is below:

while (serialPort.BytesToRead<5)
{
//Do nothing while we have less bytes than the header size
}

//Once at least 5 bytes are received, process header

As I understand it, this code is blocked and needs to be improved. I am looking for suggestions on how to do this. Would an event handler inside a DataReceived event handler be appropriate?

+7
source share
2 answers

Use asynchronous programming (remember to target your application to the .NET Framework 4.5 first).

SerialPort.

using System;
using System.IO.Ports;
using System.Threading.Tasks;

namespace ExtensionMethods.SerialPort
{
    public static class SerialPortExtensions
    {
        public async static Task ReadAsync(this SerialPort serialPort, byte[] buffer, int offset, int count)
        {
            var bytesToRead = count;
            var temp = new byte[count];

            while (bytesToRead > 0)
            {
                var readBytes = await serialPort.BaseStream.ReadAsync(temp, 0, bytesToRead);
                Array.Copy(temp, 0, buffer, offset + count - bytesToRead, readBytes);
                bytesToRead -= readBytes;
            }
        }

        public async static Task<byte[]> ReadAsync(this SerialPort serialPort, int count)
        {
            var buffer = new byte[count];
            await serialPort.ReadAsync(buffer, 0, count);
            return buffer;
        }
    }
}

:

public async void Work()
{
   try
   {
       var data = await serialPort.ReadAsync(5);
       DoStuff(data);
   }
   catch(Exception excepcion)
   {
       Trace.WriteLine(exception.Message);
   }
}
+12

100% , . , Read(). :

private byte[] rcveBuffer = new byte[MaximumMessageSize];
private int rcveLength;

void ReceiveHeader() {
    while (rcveLength < 5) {
        rcveLength += serialPort.Read(rcveBuffer, rcveLength, 5 - rcveLength);
    }
}

, DataReceived, :

    private void serialPort_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e) {
        if (e.EventType != System.IO.Ports.SerialData.Chars) return;
        if (rcveLength < 5) {
            rcveLength += serialPort.Read(rcveBuffer, rcveLength, 5 - rcveLength);
        }
        if (rcveLength >= 5) {
            // Got the header, read the rest...
        }
    }

rcveLength 0 , .

+4

Source: https://habr.com/ru/post/1543229/


All Articles