Velox
Velox

Reputation: 117

C# Application gets stuck by a blocked serial connection due to Arduino board having an internal exception after an established COM port connection

I have an issue which seems to be a big unknown to anyone on the internet, where my Windows application gets stuck when a serial connection is interrupted by the board's internal exception.

Here is the simplest example of the issue:

Simplest C# code, opening a COM port connection.

internal static class Program
{
    private static SerialPortStream _serialPort;

    static void Main()
    {
        _serialPort = new SerialPortStream("COM6", 9600, 8, Parity.None, StopBits.One);
        _serialPort.Open();
    }
}

Arduino board code, which will simulate an internal exception after a small delay.

void loop()
{
  delay(500); //We wait 0.5 seconds to allow the COM port connection to "Successfully" be established, and so the .Open() call in C# won't throw an exception.
  
  //We create an internal exception, in this instance we try to set an array size to a negative value
  int index = -4; 
  byte* serialData = new byte[index];
}

This is a very simple way to re-create this issue.

Some notable info:

Thank you to anyone who helps!

Upvotes: 5

Views: 254

Answers (1)

MSalters
MSalters

Reputation: 179779

Let's look at this problem at various levels.

At the first level (device), an exception happens.

At the second level (serial port, device side) that exception means no data is sent. The exception itself is invisible.

At the third level (serial port, PC side) no data arrives. This is not at all exceptional.

At the fourth level (serial driver, PC side) the Windows I/O subsystem works asynchronously. Every command is accepted almost immediately, and only the biggest problems cause an immediate error. Most errors are detected after a while. Common behavior like "bytes being read" are returned asynchronously, as they happen.

At the fifth layer, (synchronous API) Windows can translate synchronous calls to asynchronous I/O, simply by waiting for I/O to happen. (Assuming it happens at all - not a given for serial ports).

At the sixth layer, your C# program is using a synchronous API to access the serial port, and it's doing so from the thread that's also responsible for the UI. Hence, when that thread waits for data, everything stops. Or, you use a background thread, but then that background thread blocks.

The problem here is that you need to cancel the I/O operation. The CancelIoEx function does this, but you'll need to get the HANDLE from your SerialPortStream

Upvotes: 1

Related Questions