Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET 4 Serial Port ObjectDisposedException on Windows 7 Only

This is a problem I used to have all the time with the serial port class in .NET 2.0. It was suggested that upgrading to .NET 4 would fix the problem... and it did in almost all cases.

If I am using the serial port class built-in to .NET to communicate with a USB-to-serial adapter, and the adapter is unexpectedly unplugged while the port is open, on occasion I get an unhandled exception:

Application: test.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.ObjectDisposedException
Stack:
   at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean ByRef)
   at System.StubHelpers.StubHelpers.SafeHandleAddRef(System.Runtime.InteropServices.SafeHandle, Boolean ByRef)
   at Microsoft.Win32.UnsafeNativeMethods.GetOverlappedResult(Microsoft.Win32.SafeHandles.SafeFileHandle, System.Threading.NativeOverlapped*, Int32 ByRef, Boolean)
   at System.IO.Ports.SerialStream+EventLoopRunner.WaitForCommEvent()
   at System.Threading.ThreadHelper.ThreadStart_Context(System.Object)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

Again, most of the time it works fine. In fact, I can't even reproduce the problem on my own computers. This happens to a friend of mine. Is there any way at all to trap this error?

Edit: I was able to reproduce the behavior myself. I am experimenting now, but still am stumped as to what causes this error in .NET 4.0.

Edit 2: This seems to only happen on Windows 7. Unplugging and plugging in the USB-to-serial adapter on XP works beautifully.

like image 707
Brad Avatar asked Sep 28 '10 00:09

Brad


3 Answers

It seems that this bug won't be fixed by Microsoft any time soon, and that there is no good workaround. I've spent over a year working on this problem off-and-on.

The solution for me was to use a 3rd party component. After testing 15+, I've found that the only one that really works is CommStudio.

The free express version is here: http://www.componentsource.com/products/commstudio/downloads.html?rv=42917

like image 157
Brad Avatar answered Oct 01 '22 04:10

Brad


(I know this is a 2-year old question, but it looks like the problem is still relevant, so I'm posting some code I found that I think could be useful.)

I had a similar problem in a .NET 2.0 VB project. Often when disconnecting an USB-to-serial adapter I would get an "UnauthorizedAccessException" that crashed the program.

I haven't had the chance to port that project to .NET 4.x yet. Also, I understand the exception I was seeing is not the same as that mentioned by the OP, but I think the underlying problem might be the same, so I'd like to share a solution I found.

http://go4answers.webhost4life.com/Example/unauthorizedaccessexception-6130.aspx

The code towards the bottom of that page solved the problem for me. Here's the actual VB.NET class I used:m

Option Explicit On
Option Strict Off           ' so we can use late binding (1)

Imports System.IO.Ports

''' <summary>
''' This is a drop-in replacement for .net built-in SerialPort class.
''' It avoids "UnauthorizedAccessException" errors that sometimes happen
''' when disconnecting and reconnecting USB-to-serial adapters.
''' </summary>
''' <remarks>http://go4answers.webhost4life.com/Example/unauthorizedaccessexception-6130.aspx</remarks>

Public Class ExSerialPort

    Inherits SerialPort

    Public Sub New()
        MyBase.New()
    End Sub

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
        Dim mytype As Type = GetType(SerialPort)
        Dim field As Reflection.FieldInfo = mytype.GetField("internalSerialStream", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
        Dim stream As Object = field.GetValue(Me)

        If Not stream Is Nothing Then
            Try
                stream.Dispose()   ' (1)
            Catch ex As Exception
                ' do nothing
            End Try
        End If
        MyBase.Dispose(disposing)
    End Sub

End Class
like image 32
Marcello Romani Avatar answered Oct 01 '22 05:10

Marcello Romani


Adding the following to app.config

<runtime>
 <legacyUnhandledExceptionPolicy enabled="1"/>
</runtime>

has worked for me. See Problem with SerialPort

like image 39
Justin Wignall Avatar answered Oct 01 '22 04:10

Justin Wignall