繁体   English   中英

SerialPort UnauthorizedAccessException

[英]SerialPort UnauthorizedAccessException

有时我的某些集成测试会因上述消息而失败。 我正在使用下面的代码来准备端口。

            for(int i = 0; i < 5; i++)
            {
                try
                {
                    port.Open();
                    if (port.IsOpen)
                        break;
                }
                catch (Exception e)
                {
                    try
                    {
                        port.Close();
                    }
                    catch (Exception)
                    {}
                    Thread.Sleep(300);
                }
            }   

我的假设是因为它不能阻止端口的当前线程(因为它会尝试关闭它),它必须是另一个没有正确清理而死的线程或进程(其他测试之一 - 没有其他访问这个港口)。 有没有办法重置SerialPort的状态,以便新的线程/进程可以再次访问它?

谢谢,

理查德

这是SerialPort类中的一个缺陷,它使用内部帮助程序线程来等待端口上的事件。 DataReceived,PinChanged和ErrorReceived事件的来源。 该缺陷在Close()方法实现中,它不等待这个辅助线程终止。 这需要时间,确切的时间量是不可预测的,并且当机器特别繁忙时可能需要很多秒。 在发生这种情况之前,物理端口不会关闭,在线程退出炸弹之前打开端口并使用“已在使用的端口”例外。 你得到的那个。 因此,睡眠300毫秒是不够的。

这通常不是问题,串口不是可共享的设备。 关闭串口而不退出程序是危险的,另一个进程可能会窃取端口。 当您尝试再次打开它时也会给您这个例外。 通常的做法是在应用程序启动时打开端口,而不是关闭它直到它终止。

在我实例化串口之前,我经常验证端口是否已关闭。 如果在不关闭串行端口的情况下停止调试代码,这将有所帮 此外,在继续使用代码之前,您应该在打开或关闭端口后等待250毫秒。

try
        {
            if ((m_SerialPort != null))
            {
                if (m_SerialPort.IsOpen)
                {
                    m_SerialPort.Close();
                }
             }
             m_SerialPort = new SerialPort(portName, dataRate, parity, databits, stopBits.One);
             m_SerialPort.Open();
             if (!m_SerialPort.IsOpen)
             {
                 MessageBox.Show(string.Concat(portName, " failed to open"));
             }
         }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

我看不到你关闭港口的位置。

我的问题不在这里(即使你应该重构一下代码),但可能你正在调用port.Open(); 当端口仍然打开时

来自MSDN

每个SerialPort对象只能存在一个打开的连接。

(我不能告诉你为什么,因为我没有足够的信息)熊也记住close方法需要一些时间来实际关闭端口实际上你应该阻塞主线程直到端口关闭(也许使用的Thread.join)

来自MSDN

任何应用程序的最佳实践是在尝试调用Open方法之前等待一段时间后再调用Close方法,因为端口可能不会立即关闭。

了解更多信息

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open.aspx

应该调用GC.SuppressFinalizeGC.ReRegisterForFinalize ,将SerialPort实例BaseStream属性作为参数传递,而不仅仅是SerialPort实例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM