0
votes

I want to communicate with a DSP using RS232, so I use System.IO.SerialPort to achieve this. Everything goes well except the reading performance.

Every 200ms, the port can received a package of 144 bytes. But in the tests, the applications almost skip every other package. I try to print the system time in the console. It amaze me that the code below (when length = 140) take me over 200ms. It let the application can not handle the data in time.

Does anything wrong I do?

Port Property:

BaudRate = 9600

Parity = None

StopBits = One

    private byte[] ReadBytesInSpicifiedLength(int length)
    {
        byte[] des = new byte[length];

        for (int i = 0; i < length; i++)
        {
            des[i] = (byte)serialPort.ReadByte();
        }

        return des;
    }
1
Serial ports date from the stone-age. A traditional choice for the Baudrate is 9600 baud, it can't move data faster than about 1 msec per byte. The port settings you use are of course not a minor detail that you can leave out of a question like this.Hans Passant
@Hans: The data rate described is 720 bytes per second, which fits into 9600 baud (960 bytes per second) with some room to spare.Ben Voigt

1 Answers

1
votes

You're doing a lot of individual I/O calls, which means a lot of kernel transitions. Those are expensive. Not being able to reach 720 bytes per second is surprising, but you can make the data handling an order of magnitude faster by doing block reads:

private byte[] ReadBytesWithSpecifiedLength(int length)
{
    byte[] des = new byte[length];
    serialPort.BaseStream.Read(des, 0, des.Length);
    return des;
}

If you have timeouts enabled, you could get partial reads. Then you need to do something like:

private byte[] ReadBytesWithSpecifiedLength(int length)
{
    byte[] des = new byte[length];
    int recd = 0;
    do {
        int partial = serialPort.BaseStream.Read(des, recd, length - recd);
        if (partial == 0) throw new IOException("Transfer Interrupted");
        recd += partial;
    } while (recd < length);
    return des;
}

The nice thing about BaseStream is that it also has async support (via ReadAsync). That's what new C# code should be using.