12

我正在使用 .NET 4 SerialPort 对象与连接到 COM1 的设备通信。

完成设备后,我在 SerialPort 上调用 Close。我不叫 Dispose,但我相信 Close 和 Dispose 在这里是同义词。

通常这工作得很好。

但是,有时我会在一段时间后遇到以下异常(我看到的时间范围从 5 毫秒到 175 毫秒):

System.ObjectDisposedException:安全句柄已关闭
     在 System.Runtime.InteropServices.SafeHandle.DangerousAddRef(布尔值&成功)
     在 System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle,布尔值&成功)
     在 Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(SafeFileHandle hFile,NativeOverlapped* lpOverlapped,Int32& lpNumberOfBytesTransferred,布尔 bWait)
     在 System.IO.Ports.SerialStream.EventLoopRunner.WaitForCommEvent()
     在 System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
     在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback 回调,对象状态,布尔 ignoreSyncCtx)
     在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext,ContextCallback 回调,对象状态)
     在 System.Threading.ThreadHelper.ThreadStart()

我的代码都没有在这个堆栈上。

我找到了http://blog.zachsaw.com/2010/07/serialport-ioexception-workaround-in-c.html,但那里的解决方案不起作用。进一步检查,问题是IOException,而不是ObjectDisposedException

当 USB 转串口设备被拔出,但 COM1 是板载的,因此它不会意外消失时,有很多帖子涉及观察到的问题。

这里的问题也不是我的问题;SerialPort 在其使用期间保持活动状态,并且仅在我与设备通话完毕时才关闭。(完成后,设备处于不会传输任何进一步数据的状态。)

SLaks建议在 的入口处设置一个断点SafeHandle.Dispose,以确定我什么时候处理我不应该的东西,但我在这个断点上打了几十次。SerialPort.Close当我完成使用串行设备时,我的一次调用调用了 3 次,其余大约一半在 GC 线程中。其余部分似乎与 WPF UI 元素有关。

我现在不知所措。我从这里去哪里?

有没有办法确定哪个 SafeHandle 属于哪个对象,所以我可以确定我不会意外处置它?
除了关闭我需要正确关闭 SerialPort 之外,还有其他咒语吗?

4

2 回答 2

4

我也遇到过这个问题,自从我开始使用以下两条规则以来,我再也没有见过它。

  1. 始终调用 Close(),然后调用 Dispose()。
  2. 永远不要重用 SerialPort 对象,总是在需要重新打开端口时创建一个新对象。

我知道,它们不是什么新闻,但它一直在为我工作。

于 2011-08-18T21:33:40.827 回答
0

对处置的调用是记录在案的行为(请参见此处)-我猜您在关闭后尝试读/写(可能在另一个线程中)。我建议将调用包装在一个单独的类中并设置一个“关闭”标志。然后你应该能够相当快地找到问题。

于 2011-08-18T20:49:38.790 回答