Reputation: 21
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.
Upvotes: 2
Views: 2710
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