c# - 为什么 'using'语句好像没有释放串口?

标签 c# serial-port

我正在开发一个从托盘运行的 C# WinForms Windows 应用程序。我需要向用户提供一些合理级别的错误处理和说明。为了测试我是否能够打开串口进行通信,我希望有一种方法来测试它是否已经打开或者是否由于某种原因无法打开。

我想到了这个:

if (SerialPort.GetPortNames().Select((n) =>
    n.ToUpperInvariant()).Contains(mycomportname))
{
    // Port found, check to see if we can use it by test-opening
    using (var sp = new SerialPort(mycomportname))
    {
        // Check to see if we can open this port
        try
        {
            if (sp.IsOpen) throw new Exception("Serial port is already open");
            sp.Open();
            sp.Close();
        }
        catch (Exception ex)
        {
            throw new Exception("Serial port is in use");
        }
    } 
}
else
{
    // ...
}

commManager.PortName = mycomportname;
if (commManager.OpenPort())
{
    // .. always returns false because causes UnauthorizedAccessException on open
}

由于某种原因,串口似乎没有被'using'语句完全释放。当我删除 using 语句及其中的语句时,不会发生 UnauthorizedAccessException。如何编写健壮的容错串口打开代码?

最佳答案

MSDN article for SerialPort明确警告这一点,尽管含糊不清。 SerialPort 使用工作线程来生成事件,例如 DataReceived 和 ErrorReceived。该线程在您调用 Open() 时启动,但在您调用 Close() 或 Dispose() 后需要时间再次退出。在发生这种情况之前,物理端口一直在使用中。究竟需要多长时间是不可预测的。通常在一毫秒内,但最坏的情况是 seconds 当机器负载很重时。您的代码只等待纳秒,因此您总是会遇到异常。

否则,这种方法就没有意义。一旦你打开端口并且没有异常,那么就保持打开状态。再次关闭并重新打开它毫无意义。这是简单的解决方案。

当 GetPortNames() 返回多个端口时,从不进行这种端口扫描。第一个打开的几率非常高,它是正确的几率很低。墨菲确保五十分之一的几率变成百分之一。您总是需要提供一个配置文件,以便用户可以选择正确的配置文件。当您在配置助手窗口中使用选项填充组合框时,只考虑进行端口扫描。如果您可以控制机器配置,则只需要跳过这个,这种情况很少见。

关于c# - 为什么 'using'语句好像没有释放串口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20222098/

相关文章:

c# - 1 如果在 C# 中为 null,则以线性、美观和干净的方式分配值?

java - 如何将数据传输到串口?

C++:与 Arduino 的串行接口(interface)

c - 串行 COM 端口未打开

python - 验证串行读取

c# - 将 Gtk# Textbuffer 内容保存到文件

c# - 多次读取 IDataReader 时出错

javascript - 将 List<int> 作为 Javascript 函数的参数传递

c# - IEnumerable,需要两个实现?

embedded - 让爱普生收据打印机从 Arduino 打印