SerialPort.Close () останавливает приложение, если используемый COM-порт USB был удален - PullRequest
2 голосов
/ 29 февраля 2020

Я столкнулся с моим приложением заморозить , когда закрывается . NET C# SerialPort после того, как текущий COM-порт, подключенный к, был удален.

Выполнение SerialPort.Dispose() также зависает.

Я читал этот блог, в котором приведены некоторые объяснения (с осторожностью) относительно возможной проблемы: https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport

Может Вы помогаете мне решить эту проблему?

1 Ответ

1 голос
/ 29 февраля 2020

Я нашел обходной путь, но не уверен, что это хороший способ решить проблему.

Я использую отличную библиотеку dmitrynogin / PnP для обработки событий добавления / удаления последовательного COM-порта .

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;
}

При попытке Close() правильно SerialPort приложение зависает. Так почему бы не закрыть его, если текущий COM-порт был удален? Позже, когда COM-порт будет снова подключен, вызов Open() создаст новый экземпляр SerialPort, а затем забудет предыдущий экземпляр SerialPort, который не был закрыт должным образом. Тогда приложение не зависает и может быть нормально закрыто.

Я попробовал это, и это работает как Обходной путь, надеясь, что кто-то найдет лучшее решение.

Другим способом может быть обойти нативный . Net Класс SerialPort от SerialPortStream: jcurl / SerialPortStream независимая реализация System.IO.Ports.SerialPort и SerialStream для повышения надежности и удобства обслуживания.

С уважением

...