我正在编写一个与一台测试设备交谈的界面.设备通过串行端口进行通信,并以发送的每个命令以已知的字节数进行响应.
我目前的结构是:
>发送命令
>读回指定字节数
>继续申请
但是,当我使用SerialPort.Read(byte [],int32,int32)时,该函数没有阻塞.因此,例如,如果我调用MySerialPort.Read(byteBuffer,bytesExpected);,则函数返回小于指定的bytesExpected数.这是我的代码:
public bool ReadData(byte[] responseBytes,int bytesExpected,int timeOut) { MySerialPort.ReadTimeout = timeOut; int bytesRead = MySerialPort.Read(responseBytes,bytesExpected); return bytesRead == bytesExpected; }
我将此方法称为:
byte[] responseBytes = new byte[13]; if (Connection.ReadData(responseBytes,13,5000)) ProduceError();
我的问题是,我似乎无法像我所说的那样读取完整的13个字节.如果我在我的SerialPort.Read(…)之前放置一个Thread.Sleep(1000),一切正常.
如何超出timeOut或读取指定的字节数,如何强制Read方法阻塞?
解决方法
这是预期的;大多数IO API允许您仅指定上限 – 它们只需返回至少一个字节,除非它是EOF,在这种情况下它们可以返回非正值.要补偿,你循环:
public bool ReadData(byte[] responseBytes,int timeOut) { MySerialPort.ReadTimeout = timeOut; int offset = 0,bytesRead; while(bytesExpected > 0 && (bytesRead = MySerialPort.Read(responseBytes,offset,bytesExpected)) > 0) { offset += bytesRead; bytesExpected -= bytesRead; } return bytesExpected == 0; }
唯一的问题是您可能需要通过使用秒表或类似方法来减少每次迭代的超时,以查看已经过了多少时间.
请注意,我还删除了responseBytes上的引用 – 您不需要它(您不重新分配该值).