【问题标题】:SerialPort.Close() freezes application if the USB COM Port in use has been removed如果正在使用的 USB COM 端口已被删除,SerialPort.Close() 将冻结应用程序
【发布时间】:2020-02-29 20:45:52
【问题描述】:

我遇到了我的应用程序freeze关闭 .NET C# SerialPort 在当前连接到的 COM 端口被删除后。

执行SerialPort.Dispose() 也会冻结。

我阅读了这篇博客,其中对可能的问题给出了一些解释(请谨慎使用): https://www.sparxeng.com/blog/software/must-use-net-system-io-ports-serialport

你能帮我解决这个问题吗?

【问题讨论】:

  • 不知道为什么会冻结,但Dispose 会打电话给Close,如果这能解释什么的话。嗯
  • 这能回答你的问题吗? C# Winform freezing on SerialPort.Close
  • 在您的程序使用 USB 设备时切勿移除它。您必须使用“安全删除硬件”托盘图标,它会说“不!”只要您没有关闭端口或终止您的程序。切勿在 DataReceived 事件处理程序中使用 Invoke(),而是使用 BeginInvoke()。
  • 你是对的,但我的应用程序必须是健壮的。用户可以在使用串行 COM 端口时移除它。
  • stackoverflow.com/questions/8843301/… 不是在谈论 COM 端口在使用时的移除。我已经读过了。还是谢谢你。

标签: c# .net serial-port freeze


【解决方案1】:

我找到了一种解决方法,但不确定它是否是解决问题的好方法。

我正在使用 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 实例。然后应用程序不会冻结,可以正常关闭。

我试过了,它是一种解决方法,希望有人能找到更好的解决方案。

另一种方法是通过 SerialPortStream 绕过本机 .Net SerialPort 类: jcurl / SerialPortStream System.IO.Ports.SerialPort 和 SerialStream 的独立实现,以提高可靠性和可维护性。

最好的问候

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多