我有一个类,它使用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事件处理程序中的另一个事件处理程序是否合适?
答案 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。