简体   繁体   English

SerialPort UnauthorizedAccessException

[英]SerialPort UnauthorizedAccessException

Occasionally some of my integration tests are failing with the above message. 有时我的某些集成测试会因上述消息而失败。 I'm using the code below to ready the 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);
                }
            }   

My assumption is that because it can't be the current thread blocking the port (because it will try to close it), it must be another thread or process that has died without cleaning up properly (one of the other tests - nothing else accesses this port). 我的假设是因为它不能阻止端口的当前线程(因为它会尝试关闭它),它必须是另一个没有正确清理而死的线程或进程(其他测试之一 - 没有其他访问这个港口)。 Is there a way to reset the state of the SerialPort so that the new thread / process can access it again? 有没有办法重置SerialPort的状态,以便新的线程/进程可以再次访问它?

Thanks, 谢谢,

Richard 理查德

This is a flaw in the SerialPort class, it uses an internal helper thread to wait for events on the port. 这是SerialPort类中的一个缺陷,它使用内部帮助程序线程来等待端口上的事件。 The source of the DataReceived, PinChanged and ErrorReceived events. DataReceived,PinChanged和ErrorReceived事件的来源。 The flaw is in the Close() method implementation, it doesn't wait for this helper thread to terminate. 该缺陷在Close()方法实现中,它不等待这个辅助线程终止。 That takes time, the exact amount of time is not predictable and could be many seconds when the machine is particularly busy. 这需要时间,确切的时间量是不可预测的,并且当机器特别繁忙时可能需要很多秒。 The physical port doesn't get closed until this happens, opening the port before the thread exits bombs with a 'port already in use' exception. 在发生这种情况之前,物理端口不会关闭,在线程退出炸弹之前打开端口并使用“已在使用的端口”例外。 The one you get. 你得到的那个。 Sleeping for 300 msec is thus not good enough. 因此,睡眠300毫秒是不够的。

This is not normally an issue, serial ports are not sharable devices. 这通常不是问题,串口不是可共享的设备。 Closing a serial port and not exiting your program is dangerous, another process could steal the port. 关闭串口而不退出程序是危险的,另一个进程可能会窃取端口。 Also giving you this exception when you try to open it again. 当您尝试再次打开它时也会给您这个例外。 The normal practice is to open the port when your app starts and not close it until it terminates. 通常的做法是在应用程序启动时打开端口,而不是关闭它直到它终止。

I routinely verify that the port is closed just before I instantiate a serial port. 在我实例化串口之前,我经常验证端口是否已关闭。 This helps if you stop debugging code without closing the serial port. 如果在不关闭串行端口的情况下停止调试代码,这将有所帮 Also you should wait 250 msec after opening or closing the port before you continue with your code. 此外,在继续使用代码之前,您应该在打开或关闭端口后等待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);
        }

I can't see where you close the port. 我看不到你关闭港口的位置。

The issue for me is not here (even if you should refactor a bit the code) but probably you are calling port.Open(); 我的问题不在这里(即使你应该重构一下代码),但可能你正在调用port.Open(); when the port is still open 当端口仍然打开时

From MSDN 来自MSDN

Only one open connection can exist per SerialPort object. 每个SerialPort对象只能存在一个打开的连接。

(I can't tell you why because I don't have enough information) Bear also in mind the the close method takes some time to actually close the port in fact you should block the main thread until the port has been close (perhaps using Thread.Join) (我不能告诉你为什么,因为我没有足够的信息)熊也记住close方法需要一些时间来实际关闭端口实际上你应该阻塞主线程直到端口关闭(也许使用的Thread.join)

From MSDN 来自MSDN

The best practice for any application is to wait for some amount of time after calling the Close method before attempting to call the Open method, as the port may not be closed instantly. 任何应用程序的最佳实践是在尝试调用Open方法之前等待一段时间后再调用Close方法,因为端口可能不会立即关闭。

for more info 了解更多信息

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.open.aspx 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