Exception: COM object that has been separated from its underlying RCW cannot be used RRS feed

  • Question

  • I have the same error. And the web is full of reporting this exception and asking MS what to do about.
    In my case the exception is raised when the Garbage Collector calls Finalize on a instance of a so called "workspace object" which is developed in VB as a pice of "managed code" under VS 2008, which warppes a Collection(Of  class, and (here it comes) has a link to a COM Component (called ws_c) which is a COM collection. 

    The exception happens at ws_c = nothing below, where as ws_c is the link to an OLE/ COM type class object. 

    #Region " IDisposable Support "  
        Private Sub Dispose(ByVal disposing As Boolean)  
            SyncLock WsLock  
                If disposed Then Return  
    #If DebugMode Then  
                Debug.Print("'" & TypeName(Me) & "'    Dispose(" & disposing.ToString & ")")  
    #End If  
                If disposing Then  
                    ' Managed cleanup code here, while managed refs  
                    ' still valid  
                End If  
                ' Cleanup of unmanaged resources here  
                'release potential parent link  
                If Not m_parent_link Is Nothing Then m_parent_link = Nothing 
                'Dispose transport workspaces if any  
                If Not ws_w Is Nothing Then  
                    'ws_w = Nothing 
                End If  
                If Not ws_c Is Nothing Then  
                    'ws_c = Nothing 
                End If  
                'in addition to what we did during create  
                'we have added elements to the workspace  
                'we need to address each of it send it the Dispose()  
                'clear the collection keeping refs to the elements  
                'then set the collection as such to Nothing  
                'suggestion may we use m_col as Collection(Of ....  
                If Not m_col Is Nothing Then  
                    For Each ele As WebSpSe.ELEM In m_col  
                    'm_col = Nothing 'give up our own collection  
                End If  
                'watch that all elements of m_col terminate  
                'however this should only be required if a protocol_is not set  
                m_Name = String.Empty  
                disposed = True 
            End SyncLock  
        End Sub  
        Public Sub Dispose() Implements IDisposable.Dispose  
            ' When an object of this type wants to be explicitly cleaned-up, the user   
            ' of this object should call Dispose at the desired code location.  
            Debug.Print("WS      Dispose()" + " # " + CStr(Me.GetHashCode) + " instance " & mlClassDebugID & " " & m_Name)  
            ' We call into the helper method to perform the correct clean  
            ' Tell the garbage collector that the object doesn't require any  
            ' cleanup when collected since Dispose was called explicitly.  
        End Sub  
        Protected Overrides Sub Finalize()  
            ' Put the object cleanup code in the Finalize method  
            Debug.Print("WS     Finalize()" + " # " + CStr(Me.GetHashCode) + " instance " & mlClassDebugID & " " & m_Name)  
            ' This function can be called by Dispose() or by the GC  
            ' If called by Dispose, the application's thread executes this code  
            ' If called by the GC, then a special GC thread executes this code  
        End Sub  
    #End Region '" IDisposable Support "   
    End Class 
      Please note - the class which has this code uses a Private variable called WSLock of type Object and in the common Dispose() we use SyncLock WsLock to prevent other threads to call our code while we are i.e. calling Dispose().

    We have seen this error only when Finalize() gets called by the GC. We do not see this error when we Dispose() the WS object.

    • Split by Dan Glick - MSFT Monday, January 19, 2009 10:32 PM It looks like a new question was added to a several-month-old thread. Moving this to a new thread so we can track which questions are answered and which still need help. Also moving to the CLR forum since it appears related to COM interop.
    Monday, January 19, 2009 10:05 AM


  • > The exception happens at ws_c = nothing below

    More likely that a problem is occurring on the ws_w.Clear() after the ws_w.Dispose(). In general, Dispose() should be the last thing you call on an object (with the special case that you are allowed to call Dispose() again and it is supposed to do nothing.)  You are calling another method -- Clear() -- after you call Dispose().  Perhaps the Clear() and Dispose() calls should be reversed.  Depending on what your object actually does, the Clear() might not be necessary given that you are just going to call Dispose().

    Also of note, you need to be careful about referencing other objects in a Finalize method.  I question whether much of this code actually belongs in the If disposing Then / End If block instead.  For the cases I am most familiar with, "unmanaged resources" mainly involves using P/Invoke APIs.  Very commonly, people implement Finalize when it is not really necessary and this leads to subtle problems.  Consider that the GC should automatically release COM objects that are left unreferenced, so implementing a Finalize method that releases them is not really "helping", and will not necessarily cause them to be released any sooner.  Bottom line (IMHO): unless your class is using P/Invoke, it is highly unlikely to need a Finalize method.

    • Marked as answer by Zhi-Xin Ye Thursday, January 22, 2009 12:13 PM
    Tuesday, January 20, 2009 12:11 AM