I have defined new member in my class that is COMObject
protected COMObject.Call call_ = null;
This class has the following event handler that I subscribed to
call_.Destructed += new COMObject.DestructedEventHandler(CallDestructedEvent);
is using
Marshal.ReleaseComObject(call_)
equals to
call_.Destructed -= new COMObject.DestructedEventHandler(CallDestructedEvent);
Not at all. When you create a COM object, the object is created with the reference count of 1 on its RCW. When you subscribe to an event, the reference count is increased, because the object gets also referenced through its connection point container by a CCW, another wrapper for calls originating in the object back to your event handler.
Marshal.ReleaseComObject()decreases the counter on the RCW by one, thus you declare no intent to call the object any more. But the object still can call your event handler. This is true even if you callMarshal.ReleaseComObject()multiple times (until it returns a 0), or callMarshal.FinalReleaseComObject(), which essentially releases the object until the reference count on the RCW decreases to 0. The RCW is released, and you cannot call the object any more, but the CCW is still around, so that it can still originate events.Now, even if you managed to release the object, that would not be safe anyway: what if the call on the event handler already in progress? That would result in the object being freed with its code in active stack. The behavior is undefined in this case.
So, the safe way to release a COM object is to both unsubscribe carefully from all subscribed events and then call
Marshal.FinalReleaseComObject()to release RCW, and, by way of doing that, the object itself. Even if you do that from inside the event handler, the COM object will not die immediately, as it presumably holds an additional reference on itself while in the call, if written correctly.See also:
Runtime-Callable Wrappers
COM-Callable Wrappers
IConnectionPointContainer in the unmanaged world.