Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ObjectDisposedExecption after closing a .NET SerialPort

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?

like image 245
DaleStan Avatar asked Aug 18 '11 20:08

DaleStan


1 Answers

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.

like image 103
Per Avatar answered Oct 02 '22 20:10

Per