【发布时间】:2017-05-21 14:04:11
【问题描述】:
我正在尝试从仪表上读取数据。圣杯是设备实际支持的1000 samples per second。波特率是 38400, Parity.None 和 Stopbits.One 如果重要的话。我正在使用binary mode 让事情尽可能快。我计划如下使用 DataReceived 事件。
private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int bytesToRead = _serialPort.BytesToRead;
byte[] data = new byte[bytesToRead];
int actualBytesRead = 0;
do
{
actualBytesRead = serialPort.Read(data, 0, bytesToRead);
} while (actualBytesRead != bytesToRead);
//At this point assume that the data byte array has all the data
}
似乎BytesToRead 将返回该事件可读取的所有字节。 但是正如link 所说
The SerialPort class buffers data, but the stream object contained in the
SerialPort.BaseStream property does not. Therefore, the SerialPort object
and the stream object might differ on the number of bytes that are
available to read. When bytes are buffered to the SerialPort object, the
BytesToRead property includes these bytes in its value;
however, these bytes might not be accessible to the stream contained in
the BaseStream property.
而Read 仅返回它已读取的字节数。
因此,作为预防措施,我计划持续读取,直到读取的字节数与 BytesToRead 为引发的事件指示的字节数相同。但是有几点我不清楚。
- 这是否可行。我不确定一旦从串行端口的缓冲区中读取的数据是否会继续存在。
- 如果不是,那么在循环时,我应该保持要读取的字节数等于 BytesToRead,还是应该根据已经从缓冲区读取的字节数调整它。
- 我几乎一直在访问缓冲区,直到获得所有字节。这是正确的吗?这是否会导致锁定问题,因为字节需要更长的时间才能变得可用?
- 有没有更好的方法来获取 BytesToRead 指示的所有字节?
【问题讨论】:
-
注释很笨拙,请注意您链接到了错误的 MSDN 文章。 Read() 文章没有这个注释。区别与 Encoding 属性有关,当您读取字符串而不是字节时,它开始变得重要。就像使用 ReadExisting() 时所做的一样。 BytesToRead 总是告诉您可以读取的 bytes 数量,它不会告诉您可以读取的 characters 数量。所以不,那个 do-while 循环没有意义,它永远不会循环。
-
@HansPassant:修复了链接。串行端口article 确实提到了这一点:“因为 SerialPort 类缓冲数据,而 BaseStream 属性中包含的流没有,所以两者可能会在有多少字节可供读取方面发生冲突。BytesToRead 属性可以指示有字节要读取,但 BaseStream 属性中包含的流可能无法访问这些字节,因为它们已缓冲到 SerialPort 类。"。当 BytesToRead 指示的所有字节都可用时?
标签: c# serial-port