关闭 .NET SerialPort 后的 ObjectDisposeExecption
我正在使用 .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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我也遇到过这个问题,自从我开始使用以下两条规则以来,我再也没有见过它。
我知道,它们不是什么新闻,但它对我很有用。
I've had this issue too, and since I started using the following two rules I've never seen it again.
I know, they aren't much news, but its been working for me.
对 Dispose 的调用已记录为行为(请参阅此处< /a>) - 我猜你尝试在关闭后读/写(也许在另一个线程中)。我建议将调用包装在一个单独的类中并设置一个“关闭”标志。那么你应该能够很快找到问题所在。
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.