Com Object That Has Been Separated from Its Underlying Rcw Cannot Be Used

COM object that has been separated from its underlying RCW cannot be used

It's somewhat hard to tell what your actual application is doing, but it sounds like you may be instantiating the COM object and then attempting to access it from another thread, perhaps in a Timer.Elapsed event. If your application is multithreaded, you need to instantiate the COM object within each thread you will be using it in.

COM object that has been separated from its underlying RCW cannot be used

The issue is described here:

Is it safe to call an RCW from a finalizer?

and here:

Release Excel Object In My Destructor

The trouble is that not only is the timing as to when these objects
are to be garbage collected uncertain, but the order in which the
finalizers are called is also nondeterministic. In this case, a
Runtime Callable Wrapper also has a finalizer, which calls
Marshal.FinalReleaseComObject on itself, which has the result of
decrementing the reference count on the COM side of the fence so that
this COM object can be released. But since the order in which the
finalizers are called is uncertain, it is very possible that the
finalizers for the COM objects that your object references will fire
before the finalizer for your object. So the code within your
finalizer could work sometimes, but, most of the time, one or more of
the Runtime Callable Wrappers that your object references will have
already had their finalizers called and the underlying COM object will
have been released before your finalizer gets to execute its code.

COM object that has been separated from its underlying RCW cannot be used error related to vb.net form event

Ok so I think i've resolved this via use of the ActiveViewChanged event. Instead of rehooking the event on each form load or new document event, I tried listening for when the ActiveViewChanged event was fired and rehooking the SelectionChanged event each time. Turns out this is fired more than once each time a new document is opened (not sure why). Anyway, problem seems to have gone. Here's some example code:

Public Class MyForm

Private _activeViewEvents As IActiveViewEvents_Event
Private _docEvents As IDocumentEvents_Event

Private Sub FormLoad(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
AddHandler _docEvents.ActiveViewChanged, AddressOf ActiveViewChanged
End Sub

Private Sub ActiveViewChanged()
Dim maps = pMxDoc.Maps
For i = 0 to maps.Count - 1 'remove handlers from all maps
RemoveActiveViewEvents(maps.Item(i))
Next
SetupActiveViewEvent(pMxDoc.ActiveView.FocusMap) 'only add handler to active map
End Sub

Private Sub RemoveActiveViewEvents(map As IMap)
_activeViewEvents = CType(map, IActiveViewEvents_Event)
RemoveHandler _activeViewEvents.SelectionChanged, AddressOf SelectionChanged
End Sub

Private Sub SetupActiveViewEvents(map As IMap)
_activeViewEvents = CType(map, IActiveViewEvents_Event)
AddHandler _activeViewEvents.SelectionChanged, AddressOf SelectionChanged
End Sub

Private Sub SelectionChanged
'do something when selection is changed
End Sub

End Class

Visual Studio OrderedTests: COM object that has been separated from its underlying RCW cannot be used

Other than that, there are now good open source libraries (nuget packages) you coud use to read excel files, almost the same way you do with excel interop, but without excel, thus avoiding all possibe COM hurdles. Take a look at EPPlus or ExcelDataReader for example.

COM object that has been separated from its underlying RCW cannot be used. in oledb

As Aspirin mentioned in the comment you shouldn´t call Connection.Close on your own. But that´s not a general rule. You´re right that the connection should be closed to free unmanaged resources like a connection to the database or file-handlers. However in your case as you have an enclosing using-block that will automatically call Dipose when the variable gets out of scope and thus will call Connection.Close this latter call is done twice causing the exception when you´re closing the connection yourself.

Your using-block would be similar to this:

OleDbConnection con;
try
{
con = new OleDbConnection(...);
// ...
con.Close();
}
finally
{
if(con != null) con.Close();
}

Causing Close to be called twice on a successful run.

So you can simply omit the call to cnn.Close. because it´s allready done implicietly.

COM object that has been separated from its underlying RCW cannot be used with .NET 4.0

The simple answer is to never use Marshal.FinalReleaseComObject unless you absolutely must. And if you do, there are some additional rules you must follow.

When a COM object is used in .NET, the runtime creates what's known as a "RCW" or "runtime callable wrapper" for that object. This RCW is just a normal object that holds a COM reference on the object. When this object is garbage collected, it will call IUnknown::Release() on the COM object, as you'd expect. What this means is unless your COM object requires that the last Release() is done at a very certain moment in time, just let the garbage collector take care of it. Many COM objects fall into this case, so absolutely verify that you must manage the call to Release() carefully.

So when you're calling FinalReleaseComObject, that is essentially decrementing the reference the RCW has on the COM object until it hits zero and the RCW then releases the COM object. At this point, this RCW is now zombied, and any use of it will give the exception you've seen. The CLR (by default) only creates a single RCW for any underlying COM object, so this means if the COM API you're using returned the same object twice, it's just going to have a single RCW. Calling FinalReleaseComObjectwould mean that suddenly all uses of that RCW are toast.

The only way to guarantee you have a unique Marshal.GetUniqueObjectForIUnknown, which prevents any RCW sharing. But like I said earlier, in most COM APIs this isn't neccessary to do in the first place, so just don't do it.

Paul Harrington wrote up a good blog post about [Final]ReleaseComObject and it's evils. It's a dangerous weapon that unless needed will only hurt you. Since you're asking this question, I'd suspect you don't actually need to be calling it at all. :-)



Related Topics



Leave a reply



Submit