我在我的类中定义了COMObject
的新成员protected COMObject.Call call_ = null;
此类具有我订阅的以下事件处理程序
call_.Destructed += new COMObject.DestructedEventHandler(CallDestructedEvent);
正在使用
Marshal.ReleaseComObject(call_)
等于
call_.Destructed -= new COMObject.DestructedEventHandler(CallDestructedEvent);
答案 0 :(得分:2)
完全没有。创建COM对象时,将在其RCW上创建引用计数为1的对象。当您订阅一个事件时,引用计数会增加,因为该对象也通过CCW引用其连接点容器,另一个包装器用于将对象中的调用返回给您的事件处理程序。
Marshal.ReleaseComObject()
将RCW上的计数器减1,因此您声明无意再调用该对象。但该对象仍然可以调用您的事件处理程序。即使您多次调用Marshal.ReleaseComObject()
(直到它返回0),或者调用Marshal.FinalReleaseComObject()
,这实际上也是如此,这实际上释放了对象,直到RCW 上的引用计数减少为止RCW已经发布,你不能再调用该对象,但是CCW仍然存在,所以它仍然可以发起事件。
现在,即使您设法释放了该对象,但无论如何这都不安全:如果对事件处理程序的调用已经在进行中该怎么办?这将导致对象被释放,其代码在活动堆栈中。在这种情况下,行为是未定义的。
因此,释放COM对象的安全方法是从所有订阅的事件中仔细取消订阅,然后调用Marshal.FinalReleaseComObject()
来释放RCW,并通过这样做,对象本身。即使您从事件处理程序内部执行此操作,COM对象也不会立即死亡,因为如果正确写入,它可能会在调用期间保留其自身的附加引用。
另见:
Runtime-Callable Wrappers
COM-Callable Wrappers
IConnectionPointContainer在未管理的世界中。