SerialPort UnauthorizedAccessException

时间:2011-09-08 13:10:54

标签: c# serial-port

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

            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的状态,以便新线程/进程可以再次访问它?

谢谢,

理查德

4 个答案:

答案 0 :(得分:14)

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

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

答案 1 :(得分:5)

在我实例化串口之前,我经常验证端口是否已关闭。如果在不关闭串行端口的情况下停止调试代码,这将有所帮此外,在继续使用代码之前,您应该在打开或关闭端口后等待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);
        }

答案 2 :(得分:2)

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

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

来自MSDN

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

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

来自MSDN

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

了解更多信息

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

答案 3 :(得分:0)

应该调用

GC.SuppressFinalizeGC.ReRegisterForFinalize传递SerialPort实例BaseStream属性作为参数而不仅仅是SerialPort实例。