3

I do some very simple error logging in my desktop application which speaks to equipment over a SerialPort. One thing I do is setup a global exception catcher which does nothing but log the stack trace using:

AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler;

I have one user who is having an error that is showing up in his logs. No one else is having the issue. I have no idea where to search for this uncaught exception. And I have no idea where I should try to catch it because I don't fully understand what it is.

I use the .NET SerialPort object and all I do in open the port and do some simple reads and writes.

Is anyone able to explain what this exception is/means, what I can do to fix it, or where I should look to try and catch the error? Every time I touch my SerialPort object I am doing so within try and catch blocks. So I am at a complete loss.

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.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, 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()
Michael Mankus
  • 4,628
  • 9
  • 37
  • 63
  • What's the stack trace? – SLaks Feb 27 '14 at 18:19
  • 1
    "The exception that is thrown when an operation is performed on a disposed object." – O.O Feb 27 '14 at 18:23
  • Haha sorry I completely forgot to add the StackTrace – Michael Mankus Feb 27 '14 at 18:29
  • @O.O My apologies since I didn't have the StackTrace in there when you commented. I realize how that type of exception is thrown. But the trace offers me no information (that I can see) on how to capture it or prevent it. It appears to be a .NET problem. – Michael Mankus Feb 27 '14 at 18:30
  • @MichaelMankus - it appears the exception is being thrown on a different thread. Move your try-catch block into the thread that does the read/writing and see if that fixes your problem. – O.O Feb 27 '14 at 18:35
  • @O.O Wow you know that never even occurred to me. The only thing I have threaded to my call to `SerialPort.Close()`. And you are right that I thread my call to that method and therefore my try/catch is not observed. Very silly of me. – Michael Mankus Feb 27 '14 at 18:48
  • It is caused by the serial port driver that the user is using, it is making the port disappear while you have it in use. Typically a cr*ppy one that he spent five bucks on. Next best thing to tell him is to not jerk the USB connector while your program is running. – Hans Passant Feb 27 '14 at 18:49

2 Answers2

3

I used some assistance from user O.O and from this SO question. I was doing something silly.

public bool OpenPort()
{
    try
    {
        if (_port != null && _port.IsOpen)
        {
            new Thread(_port.Close).Start();
            Thread.Sleep(500);
        }

        // Open the port code

        return true;
    }
    catch (Exception e)
    {
        // Error handling code
        return false;
    }
}

I was doing what you see above. Because I was threading the call to close, my Try/Catch did nothing. And from the answer to the other SO question, it looks like calling SerialPort.Close() without also calling Dispose() is the issue.

public bool OpenPort()
{
    try
    {
        if (_port != null && _port.IsOpen)
        {
            new Thread(CloseSerialPortCleanly).Start();
            Thread.Sleep(500);
        }

        // Open the port code

        return true;
    }
    catch (Exception e)
    {
        // Error handling code
        return false;
    }
}

private void CloseSerialPortCleanly()
{
    try
    {
        if (_port != null && _port.IsOpen)
        {
            _port.Close();
            _port.Dispose();
            _port = null;
        }
    }
    catch
    {
         // Error handling code
    }
}

This has solved the user's issue.

Community
  • 1
  • 1
Michael Mankus
  • 4,628
  • 9
  • 37
  • 63
1

It appears the exception is being thrown on a different thread. Move your try-catch block into the thread that does the read/writing and see if that fixes your problem.

Also see this question for using Task.

Community
  • 1
  • 1
O.O
  • 11,077
  • 18
  • 94
  • 182