在SerialPort中,调用“关闭”而不是“处置”时访问被拒绝

时间:2019-02-14 14:51:33

标签: c# serial-port dispose unauthorizedaccessexcepti

更新1

我发现,如果我颠倒了关闭/处置的顺序,那么我会从处置而不是关闭中得到错误...因此,可能的一次性保护意味着该方法仅被调用一次。

通过在一条数据线上建立接地短路,我已经能够在设备上复制错误。我在设备上使用的是FT230x,发现如果短接复位引脚,则可以恢复通信,但是现在,一旦执行此操作,我就会从应用程序中获得另一个异常。因此,从技术上讲,我的应用程序现在将在重启时重新连接,这是一个改进,与以前一样,我必须物理拔出并重新插入设备。下面的新异常:

System.ObjectDisposedException
  HResult=0x80131622
  Message=Safe handle has been closed
  Source=mscorlib
  StackTrace:
   at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success)
   at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success)
   at Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(SafeFileHandle hFile, NativeOverlapped* lpOverlapped, Int32& lpNumberOfBytesTransferred, Boolean bWait)
   at System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

奇怪的是,调用堆栈不包含我的任何代码,而Visual Studio不允许我将其追溯到我的代码。

原始帖子

我有一个在SerialPort.Write上给我IOException的设备,然后当我尝试关闭端口时,我得到了UnauthorizedAccessException。之后,我可以毫无例外地处理串行端口,但是尝试重新打开端口会导致UnauthorizedAccessException。当我继续阅读Dispose和Close应该做完全相同的事情时,我真正的困惑就出现了。有没有一种方法可以使我从中恢复而无需重新启动程序(或在某些情况下为计算机)?

在我的项目中,我管理使用同一COM端口或使用唯一COM端口的多个设备。因此,我有一个管理员来管理我的设备,找到它们的端口,并为这些设备创建端口管理器。有时设备会断开连接,当发生这种情况时,我会关闭并处置com端口和com端口管理器。下面是我的代码:

private void DisposeComPort()
{
    if (ComPort != null)
    {
        string message = "Disposing Com Port.";
        try
        {
            ComPort.DataReceived -= ComPort_DataReceived;
            ComPort.ErrorReceived -= ComPort_ErrorReceived;
            message += " Com Port Events Unsubscribed.";

        }
        catch (Exception ex)
        {
            HandleException(this, ex, "Exception attempting to remove Handlers for on " + this.ToString() + ".");

        }
        try
        {
            if (ComPort.IsOpen)
            {
                ComPort.Close(); message += " Com Port Closed.";
            }
        } catch(Exception ex)
        {
            HandleException(this, ex, "Exception attempting to close on " + this.ToString() + ".");
        }
        try
        {
            ComPort.Dispose(); message += " Com Port Disposed.";
        } catch (Exception ex)
        {
            HandleException(this, ex, "Exception attempting to Dispose Com Port on " + this.ToString() + ".");
        }
        ComPort = null;
        LogMessage(this, message);
    }
}

当我尝试ComPort.Write()时,每隔几天就有一个设备给我“ System.IO.IOException:连接到系统的设备无法运行”。发生这种情况时,我尝试处置我的COM端口。在正常情况下,我可以关闭端口并重新打开它,但是在这种情况下,我的代码无法关闭并成功处理,但是当我的设备管理器尝试重新打开COM端口时,我继续得到UnauthorizedAccessException。以下是我的异常日志。

11:26:35.862, Exception Sending Com Packet to Device 34 on ModbusPortManager Port COM4 Created 6:30:48 AM.
System.IO.IOException: A device attached to the system is not functioning.

   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream.EndWrite(IAsyncResult asyncResult)
   at System.IO.Ports.SerialStream.Write(Byte[] array, Int32 offset, Int32 count, Int32 timeout)
   at System.IO.Ports.SerialPort.Write(Byte[] buffer, Int32 offset, Int32 count)
   at ModbusPortManager.TransmitPacket(IModbusDevice device, ComPacket packet, Int32 packetIndex) in Classes\ModbusPortManager.cs

-----------------------------------------------------------------------------

11:26:35.880, Disposing Timers. Stopped MessageReceived EventWaitHandle. Stopped PacketTimeoutTimer Timer. Stopped RetransmitTimer Timer. Stopped AgePrioritizerTimer Timer. Stopped 4/4. ~ ModbusPortManager Port COM4 Created 6:30:48 AM Disposed

-----------------------------------------------------------------------------

11:26:35.894, Exception attempting to close on ModbusPortManager Port COM4 Created 6:30:48 AM Disposed.
System.UnauthorizedAccessException: Access to the port is denied.
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.InternalResources.WinIOError()
   at System.IO.Ports.SerialStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Ports.SerialPort.Dispose(Boolean disposing)
   at System.IO.Ports.SerialPort.Close()
   at ModbusPortManager.DisposeComPort() in Classes\ModbusPortManager.cs

-----------------------------------------------------------------------------

11:26:35.904, Disposing Com Port. Com Port Events Unsubscribed. Com Port Disposed. ~ ModbusPortManager Port COM4 Created 6:30:48 AM Disposed

-----------------------------------------------------------------------------

11:26:36.934, Port Manager Created. ~ ModbusPortManager Port COM4 Created 11:26:36 AM

-----------------------------------------------------------------------------

11:26:36.947, Exception Testing on ModbusPortManager Port COM4 Created 11:26:36 AM

System.UnauthorizedAccessException: Access to the port 'COM4' is denied.
   at ModbusPortManager.OpenPort() in Classes\ModbusPortManager.cs
   at ModbusPortManager.TestPort() in Classes\ModbusPortManager.cs

-----------------------------------------------------------------------------

1 个答案:

答案 0 :(得分:1)

最终通过实现ObjectDisposedException when closing SerialPort in .Net 2.0中的解决方案和http://zachsaw.blogspot.com/2010/07/net-serialport-woes.html中的类来解决System.ObjectDisposedException问题

SerialPortFixer类在某些端口上抛出了无效的参数,但是在我的设备上却没有,并且不再发生异常,该异常导致重新连接时使程序崩溃。