关闭 .NET SerialPort 后的 ObjectDisposeExecption

发布于 2024-11-30 11:08:32 字数 2082 浏览 1 评论 0原文

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

当我使用完设备后,我在串行端口上调用 Close。我不调用 Dispose,但我相信 Close 和 Dispose 在这里是同义词。

通常这工作得很好。

然而,有时,一段时间后我会收到以下异常(我看到的时间范围从 5 毫秒到 175 毫秒):

System.ObjectDisposedException: Safe handle has been closed
     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.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
     at System.Threading.ThreadHelper.ThreadStart()

我的代码都不在此堆栈上。

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

有大量关于拔出 USB 转串口设备时观察到的问题的帖子,但 COM1 是板载的,因此它不会意外消失。

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

SLAks 建议SafeHandle.Dispose的入口处设置一个断点,以确定我何时处理不应该处理的东西,但我多次敲击该断点。当我使用完串行设备后,对 SerialPort.Close 的一次调用会调用 3 次,其余的大约一半在 GC 线程中。其余部分似乎与 WPF UI 元素有关。

我现在很茫然。我该去哪里?

有没有办法确定哪个 SafeHandle 属于哪个对象,这样我就可以确定我不会意外地处置它?
除了“关闭”之外,是否还有其他咒语需要正确关闭串行端口?

I am using a .NET 4 SerialPort object to talk to a device attached to COM1.

When I am done with the device, I call Close on the SerialPort. I do not call Dispose, but I believe that Close and Dispose are synonymous here.

Usually this works just fine.

Sometimes, however, I get the following exception some time later (The times I've seen range from 5 ms to 175 ms):

System.ObjectDisposedException: Safe handle has been closed
     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.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
     at System.Threading.ThreadHelper.ThreadStart()

None of my code is on this stack.

I found http://blog.zachsaw.com/2010/07/serialport-ioexception-workaround-in-c.html, but the solution there did not work. On further inspection, the issue there is an IOException, not an ObjectDisposedException.

There are a plethora of posts concerning issues observed when a USB-to-serial device is unplugged, but COM1 is onboard, so it isn't vanishing unexpectedly.

The problem here is also not my issue; the SerialPort is kept alive for the duration of its use, and is closed only when I am done talking to the device. (Once I am done, the device is in a state where it will not transmit any further data.)

SLaks suggests setting a breakpoint on the entrance to SafeHandle.Dispose, to determine when I'm disposing something I shouldn't be, but I strike that breakpoint dozens of times. Three times are called by my single call to SerialPort.Close, when I am done using the serial device, and about half the rest are in the GC thread. The remainder seem to be related to WPF UI elements.

I am now at a loss. Where do I go from here?

Is there a way to determine which SafeHandle belongs to which object, so I can be certain I'm not disposing it unexpectedly?
Is there some incantation other than Close I need to properly shut down a SerialPort?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

国际总奸 2024-12-07 11:08:32

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

  1. 始终调用 Close(),然后调用 Dispose()。
  2. 切勿重复使用 SerialPort 对象,当需要重新打开端口时,始终创建一个新对象。

我知道,它们不是什么新闻,但它对我很有用。

I've had this issue too, and since I started using the following two rules I've never seen it again.

  1. Always call Close() followed by Dispose().
  2. Never reuse a SerialPort object, always create a new one when a port needs to be reopened.

I know, they aren't much news, but its been working for me.

橘味果▽酱 2024-12-07 11:08:32

The call to disposed is documented behavior (see here) - I guess you try to read/write after Close (maybe in another thread). I would suggest wrapping the calls in a seperate class and setting a "closed"-flag. Then you should be able to find the problem rather fast.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文