ReleaseComObject 是否等于取消订阅事件处理程序?
我在我的类中定义了新成员 COMObject
protected COMObject.Call call_ = null;
该类具有以下我订阅的事件处理程序,
call_.Destructed += new COMObject.DestructedEventHandler(CallDestructedEvent);
使用
Marshal.ReleaseComObject(call_)
等于
call_.Destructed -= new COMObject.DestructedEventHandler(CallDestructedEvent);
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);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一点也不。当您创建 COM 对象时,该对象在其 RCW 上的引用计数为 1。当您订阅事件时,引用计数会增加,因为 CCW 也通过其连接点容器引用该对象,CCW 是源自对象的调用返回事件处理程序的另一个包装器。
Marshal.ReleaseComObject()
将 RCW 上的计数器减一,因此您声明不再打算调用该对象。但该对象仍然可以调用您的事件处理程序。即使您多次调用Marshal.ReleaseComObject()
(直到返回 0),或者调用Marshal.FinalReleaseComObject()
(这实际上会释放对象,直到RCW 上的引用计数减少到 0。RCW 被释放,您不能再调用该对象,但 CCW 仍然存在,因此它仍然可以发起事件。现在,即使您设法释放该对象,无论如何也不安全:如果对事件处理程序的调用已经在进行中怎么办?这将导致该对象及其在活动堆栈中的代码被释放。在这种情况下,行为是未定义的。
因此,释放 COM 对象的安全方法是小心地取消订阅所有订阅的事件,然后调用 Marshal.FinalReleaseComObject() 来释放 RCW,并通过这样做释放对象本身。即使您从事件处理程序内部执行此操作,COM 对象也不会立即消亡,因为如果编写正确的话,它在调用过程中可能会保留对其自身的附加引用。
另请参阅:
运行时可调用包装器
COM 可调用包装
IConnectionPointContainer 在不受管理的世界。
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.