C#异步串口读取

时间:2014-06-04 15:20:24

标签: asynchronous serial-port blocking

我有一个类,它使用C#中的DataReceived事件处理程序从串口读取。当我收到数据时,我知道标题将有5个字节,所以我不想对数据做任何事情,直到我至少有。我目前的代码如下:

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

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

据我了解,此代码是阻塞的,需要进行改进。我正在寻找有关如何做到这一点的建议。 DataReceived事件处理程序中的另一个事件处理程序是否合适?

2 个答案:

答案 0 :(得分:12)

使用异步编程(不要忘记首先将应用程序定位到.NET Framework 4.5)。

在这里,您将我的实现作为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) { int quedanPorLeer = count; var temp = new byte[count]; while(quedanPorLeer > 0) { int leidos = await serialPort.BaseStream.ReadAsync(temp, 0, quedanPorLeer); Array.Copy(temp, 0, buffer, offset + count - quedanPorLeer, leidos); quedanPorLeer -= leidos; } } public async static Task<byte[]> ReadAsync(this SerialPort serialPort, int count) { var datos = new byte[count]; await serialPort.ReadAsync(datos, 0, count); return datos; } } } 的扩展方法。

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

以及如何阅读:

//Init Chartboost
    Chartboost.startWithAppId(this, getString(R.string.chartboost_app_id), getString(R.string.chartboost_app_signature));
    Chartboost.setImpressionsUseActivities(true);
    Chartboost.setShouldRequestInterstitialsInFirstSession(false);
    Chartboost.setDelegate(cbDelegate);
    Chartboost.onCreate(this);

答案 1 :(得分:5)

燃烧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。