我有一个使用RS-232从无线电接收数据的应用程序。这些无线电使用API​​与多个客户端进行通信。为了使用无线电,我创建了一个与它们进行通信的库,其他软件可以利用这些库与常规SerialPort连接进行最小的更改。该库从SerialPort对象读取,然后根据接收到的无线电将输入的数据插入不同的缓冲区。每个接收到的数据包都包含一个标头,指示其长度,源等。

我首先从端口读取固定长度的标头并进行解析。在标题中,数据的长度是在数据有效载荷本身之前定义的,因此一旦我知道了数据的长度,便会等待那么多的数据可用,然后再读取那么多的字节。

示例(省略标题中的其他元素):

// Read header
byte[] header = new byte[RCV_HEADER_LENGTH];
this.Port.Read(header, 0, RCV_HEADER_LENGTH);

// Get length of data in packet
short dataLength = header[1];
byte[] payload = new byte[dataLength];

// Make sure all the payload of this packet is ready to read
while (this.Port.BytesToRead < dataLength) { }

this.Port.Read(payload, 0, dataLength);


显然,空端口是坏的。如果由于某种原因数据永不到达,线程将锁定。我还没有遇到这个问题,但是我正在寻找一种优雅的方式来做到这一点。我的第一个想法是添加一个简短的计时器,该计时器在while循环之前开始,并在其终止时设置abortRead标志,这会中断while循环,如下所示:

// Make sure all the payload of this packet is ready to read
abortRead = false;
readTimer.Start();
while (this.Port.BytesToRead < dataLength && !abortRead) {}


这段代码需要尽快处理恒定的传入数据流,因此将开销降到最低是一个问题,并且想知道我是否做得正确。

最佳答案

您不必运行while循环,方法Read会为您填充缓冲区,或者在TimeoutException时间内未填充缓冲区时会抛出SerialPort.ReadTimeout(您可以根据需要进行调整) )。

但是有一些一般性的说明-您的while循环会导致CPU大量工作,而在几毫秒之内它将需要数据才能到达,而while循环迭代将使您有大量的这些,您应该在其中添加一些Thread.Sleep

关于c# - 在C#中等待来自串行端口的数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41622117/

10-08 23:54
查看更多