Adam Rosas
Adam Rosas

Reputation: 21

Problems with SerialPort class in .NET

I'm trying to diagnose why some USB serial port adapters do not work well with .NET. The behavior of the affected adapters is after SerialPort.Write(). Calling any of the SerialPort.Readxxx() methods causes the method to block until about ReadTimout. The workaround that I have discovered is to use a loop to block while BytesToRead is <= 0, and then everything works as expected. Why?

I have collected some debug logs using Sysinternals' Portmon. Why is this happening?

without.log = bad behavior/bad USB adapter
with.log = with the while loop/bad USB adapter
ftdi.log = good behavior/good USB adapter

I wrote two native implementations of ReadByte() and can now better characterize the issue. With ReadIntervalTimeout and ReadTotalTimeoutMultiplier set to MAXDWORD ReadFile(), it is supposed to wait until a byte is in the receive buffer and return as described on MSDN's COMMTIMEOUTS structure page.

The Portmon logs show that this is how ReadByte() is setting up the serial port. But if the receive buffer is empty when ReadFile() is called ReadFile() it waits until ReadTotalTimeoutConstant and then returns. Microsoft's ReadByte() also sets up a Comm event; the Portmon logs clearly shows the event is firing, but ReadByte() never reads the receive buffer. I implemented this in my native version of ReadByte() and it works perfectly with the affected USB-to-serial adapter.

Native ReadByte()

Upvotes: 2

Views: 2710

Answers (1)

Aleksej Vasinov
Aleksej Vasinov

Reputation: 2797

The best idea to read SerialPort is using async-ous method:

_port = new SerialPort();
_port.DataReceived += new SerialDataReceivedEventHandler(OnComPortDataReceived);

void OnComPortDataReceived(object sender, SerialDataReceivedEventArgs e)
{
   byte[] ba = new byte[_port.BytesToRead];
   total = _port.Read(ba, 0, _port.BytesToRead);
}

Upvotes: 1

Related Questions