2

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()

1 Answer 1

1

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);
}
Sign up to request clarification or add additional context in comments.

8 Comments

the DataReceivedEvent isn't guaranteed to fire, and in my testing 40% of the events never reach the app
Could you explain why "DataReceivedEvent isn't guaranteed to fire"?
Rather strange problem. Maybe your adapter is not working good. I've checked with my old GSM phone (connected to USB as modem), tried to send some AT commands and everything is ok. I've checked it with portmon also... Could you post your code here?
I think, that you are C/C++ programmer :) When I came to C# I worked with serial the same way. But you should switch to events, really! I suggest you to log every byte in DataReceivedEvent handler and to check whether all data came
This code is used to move a telescope, I have had two uncontrolled slews trying to use events, not reliable enough for my use. I had an DataRecievedEvent handler that all it did was incriment a counter and found that up to 40% of the events got lost. weather or not I should be using events is not the question.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.