SerialPort UnauthorizedAccessException

本文关键字:UnauthorizedAccessException SerialPort | 更新日期: 2023-09-27 18:07:54

偶尔我的一些集成测试会因为上述消息而失败。我使用下面的代码来准备端口。

            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 UnauthorizedAccessException

这是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

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

查看更多信息

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

GC.SuppressFinalize应该通过SerialPort实例BaseStream属性作为参数来调用,而不仅仅是SerialPort实例

public class SerialConnection : SerialPort
{
    public new void Dispose()
    {
        if (_isDisposed)
            return;
        _isDisposed = true;
        BaseStream.Dispose();
        GC.SuppressFinalize(BaseStream);
        base.Dispose();
        GC.SuppressFinalize(this);
    }

new void Dispose()当然不是推荐实现IDisposable的方法。这只是对SerialPort类的奇怪行为的修复。

实际上,我认为有一个非常简单的解决方案。我遇到了同样的问题,只是关闭了Arduino IDE因为这个端口被arduino占用了。然后在visual studio中重新启动应用程序,问题就解决了。简而言之,如果端口忙于其他应用程序,则关闭此应用程序

相关文章:
  • 没有找到相关文章