SerialPort.Read(byte[], int32, int32) is not blocking but i want it to - how do I achieve?

一个人想着一个人 提交于 2019-12-23 21:06:51

问题


I'm writing an interface for talking to a piece of test equipment. The equipment talks over a serial port and responds with a known number of bytes to each command I send it.

My current structure is:

  • Send command
  • Read number of specified bytes back
  • Proceed with application

However, when I used SerialPort.Read(byte[], int32, int32), the function is not blocking. So, for example, if I call MySerialPort.Read(byteBuffer, 0, bytesExpected);, the function returns with less than the specified number of bytesExpected. Here is my code:

public bool ReadData(byte[] responseBytes, int bytesExpected, int timeOut)
{
    MySerialPort.ReadTimeout = timeOut;
    int bytesRead = MySerialPort.Read(responseBytes, 0, bytesExpected);
    return bytesRead == bytesExpected;
}

And I call this method like this:

byte[] responseBytes = new byte[13];
if (Connection.ReadData(responseBytes, 13, 5000))
    ProduceError();

My problem is that I can't ever seem to get it to read the full 13 bytes like I am telling it. If I put a Thread.Sleep(1000) right before my SerialPort.Read(...) everything works fine.

How can I force the Read method to block until either the timeOut is exceeded or the specified number of bytes are read?


回答1:


That is expected; most IO APIs allow you to specify the upper bound only - they are simply required to return at-least-one byte, unless it is an EOF in which case they can return a non-positive value. To compensate, you loop:

public bool ReadData(byte[] responseBytes, int bytesExpected, 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;
}

The only problem is you might need to reduce the timeout per iteration, by using a Stopwatch or similar to see how much time has passed.

Note that I also removed the ref on responseBytes - you don't need that (you don't re-assign that value).




回答2:


Try changing the timeout to InfiniteTimeout.




回答3:


SerialPort.Read is expected to throw a TimeoutException in case no bytes are available before SerialPort.ReadTimeout. So this method reads exactly the desired number or bytes, or throws an exception:

    public byte[] ReadBytes(int byteCount) {
        try
        {
            int totBytesRead = 0;
            byte[] rxBytes = new byte[byteCount];
            while (totBytesRead < byteCount) {
                int bytesRead = comPort.Read(rxBytes, totBytesRead, byteCount - totBytesRead);
                totBytesRead += bytesRead;
            }



            return rxBytes;
        }
        catch (Exception ex){

            throw new MySerialComPortException("SerialComPort.ReadBytes error", ex);            
        }
    }


来源:https://stackoverflow.com/questions/16439897/serialport-readbyte-int32-int32-is-not-blocking-but-i-want-it-to-how-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!