Kevin
Kevin

Reputation: 65

Virtual ComPort stops calling DataReceived after some time

I am currently stuck at a problem which I cant find any answer for. I am controlling a device that is attached to the computer via a Virtual-ComPort (USB). For this communication I use the SerialPort class in System.IO.Ports.

This is how I initialize the port:

SerialPort SerialPort = new SerialPort();
SerialPort.BaudRate = BaudRate;
SerialPort.DataBits = 8;
SerialPort.Parity = Parity.None;
SerialPort.PortName = SerialPortName;
SerialPort.StopBits = StopBits.One;
SerialPort.ReceivedBytesThreshold = 9;
SerialPort.WriteTimeout = 1500;
SerialPort.ReadTimeout = 1500;
SerialPort.DataReceived += dataReceivedHandler;
SerialPort.Open();

I set the received Threshold to 9 because I know that all the data I can receive is 9 bytes long and I want to minimize the number of callbacks. Can this cause any harm?

This does work really well in 99,99% of all cases. But after a random amount of time/commands (typically after several thousand operations) I don't get a callback when data is send to the PC. The DataReceived handler is just not called in these cases. I checked this by adding a Debug.WriteLine("Callback received!") at the very beginning of the dataReceivedHandler.

I am sure the data is send by the device I like to control. What is the cause of this seemingly "random" behavior and how can I fix it?

I am grateful for any suggestions.

Best Nano

Upvotes: 1

Views: 687

Answers (1)

Hans Passant
Hans Passant

Reputation: 941465

Using ReceivedBytesThreshold is a convenience, but it only works when the Sun is shining and you've got a stiff breeze in your back. You are skipping the things you need to do to ensure it can work:

  • You need to implement flow control so there is no scenario where the device can overflow the input buffer. Even though modern machines are plenty fast enough to support a high baudrate, they cannot guarantee that they are always fast enough. Losing the processor for many hundreds of milliseconds is very possible. You should always set the Handshake property so this can never happen. The proper value depends on what the device supports, always start with Handshake.RequestToSend if you don't know.

  • Never checking for errors is pretty much a guarantee that you cannot diagnose a mishap like this. Implementing the ErrorReceived event handler is not optional. It is the only way you can diagnose mishaps, like a UART or device driver input buffer overflow, the kind that cause data loss and cause the kind of trouble you are trying to troubleshoot.

  • ReceivedBytesThreshold always gives you a synchronization problem. You have to make sure that you start listening at just the right time, in between two chunks of 9 bytes. That is of course pretty hard to do if you have no control over the startup order of your program vs the device, you rarely do. A decent protocol always gives you a way to synchronize, typically with a dedicated byte value that indicates the start of a message. Once you have that, the value of the ReceivedBytesThreshold completely disappears.

Start with the ErrorReceived event so you know when things go wrong. Shopping for another USB emulator also ought to be high on your list of possible workarounds, drivers for them are generally pretty cruddy.

Upvotes: 2

Related Questions