3

I faced my application freeze, when closing .NET C# SerialPort after the current COM Port connected to, has been removed.

Doing a SerialPort.Dispose() freezes also.

I read this blog which gave some explainations (to take with caution) on the possible issue : https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport

Could you help me solving this issue ?

  • Not sure why the freeze but `Dispose` will call `Close` if that explains anything. Hmm –  Feb 28 '20 at 23:30
  • 1
    Does this answer your question? [C# Winform freezing on SerialPort.Close](https://stackoverflow.com/questions/8843301/c-sharp-winform-freezing-on-serialport-close) –  Feb 28 '20 at 23:35
  • Never remove a USB device while your program is using it. You *must* use the "Safely remove hardware" tray icon, it will say "No!" as long as you haven't closed the port or terminated your program. Never use Invoke() in a DataReceived event handler, use BeginInvoke() instead. – Hans Passant Feb 28 '20 at 23:39
  • 2
    You are right, but my application must be robust. The user could remove a serial COM Port whilst it is in use. –  Feb 28 '20 at 23:58
  • 2
    https://stackoverflow.com/questions/8843301/c-sharp-winform-freezing-on-serialport-close is not talking about COM Port removal when it is in use. I already read it. Thank you anyway. –  Feb 29 '20 at 00:00

1 Answers1

0

I found a workaround but not sure it's a good way to solve the issue.

I'm using the dmitrynogin / PnP excellent library to handle serial COM Port add/remove events.

private SerialPort _serialPort;
...
private void Main()
{
    ...
    Open();         // Open COM Port
    ...             // Do Stuff

}
...
// COM Port removed event
private void PortCOMRemoved()
{
    ...
    Close(true);
    ...
}
...
private void Close(bool currentCOMPortRemoved = false)
{    
    ...
    if (currentCOMPortRemoved)
    {
        _serialPort.DtrEnable = false;
        _serialPort.RtsEnable = false;
        _serialPort.DiscardInBuffer();
        _serialPort.DiscardOutBuffer();
        // Do not close the COM Port, otherwise, it will freeze
        // This is a Bug in SerialPort class management Framework
        // On next connexion, it will create a new SerialPort instance
        // Application can close itself
    }
    else
    {
        _serialPort.Close();
    }
    ...
}

...
private bool Open()
{
    bool success = false;

    Close();

    try
    {
        _serialPort = new SerialPort();
        _serialPort.ErrorReceived += HandleErrorReceived;
        _serialPort.PortName = _portName;
        _serialPort.BaudRate = _baudRate;
        _serialPort.StopBits = _stopBits;
        _serialPort.Parity = _parity;
        _serialPort.DataBits = (int)_dataBits;
        _serialPort.ReadTimeout = 1000;

        // We are not using serialPort.DataReceived event for receiving data since     this is not working under Linux/Mono.
        // We use the readerTask instead (see below).
        _serialPort.Open();
        success = true;
    }
    catch (Exception e)
    {
        Close();
    }

    return success;
}

When trying to Close() properly the SerialPort the application freeze. So why not closing it if the current COM Port has been removed ? Later when the COM Port will be plugged again, a call to Open() will create a new instance of SerialPort then forget the previous SerialPort instance that was not Closed properly. Then the application don't freeze and can be closed normaly.

I tryed it and it's working as a Workaround hoping someone will find a better solution.

Another way could be to bypass the native .Net SerialPort class by SerialPortStream : jcurl / SerialPortStream an independent implementation of System.IO.Ports.SerialPort and SerialStream for better reliability and maintainability.

Best regards