2012-01-17 46 views
0

我已經在我的課是COMObjectReleaseComObject是否等於取消訂閱事件處理程序?

protected COMObject.Call call_ = null; 

這個類有下面的事件處理,我訂閱了

call_.Destructed += new COMObject.DestructedEventHandler(CallDestructedEvent); 

使用

Marshal.ReleaseComObject(call_) 

等於

定義的新成員
call_.Destructed -= new COMObject.DestructedEventHandler(CallDestructedEvent); 
+0

它可能是。事件很奇怪,一個COM對象不能被破壞,除非所有的接口引用都計數到零。只要您訂閱了該活動,該計數就不會達到零。不應該。設計非常*可腥。 –

回答

2

完全沒有。創建COM對象時,該對象的RCW上引用計數爲1。當你訂閱一個事件時,引用計數會增加,因爲該對象也是通過它的連接點容器被CCW引用的,而另一個包裝器則是將對象中的調用發回給你的事件處理程序。

Marshal.ReleaseComObject()將RCW上的計數器減1,因此您聲明無意再調用該對象。但該對象仍然可以調用您的事件處理程序。即使多次呼叫Marshal.ReleaseComObject()(直到它返回0),或者調用Marshal.FinalReleaseComObject(),這實際上釋放對象,直到RCW上的引用計數減少爲0,這也是如此。RCW被釋放,並且您不能調用反對,但CCW仍在,因此它仍然可以發起事件。

現在,即使您設法釋放對象,反正也不安全:如果事件處理程序的調用已在進行中,該怎麼辦?這會導致該對象在活動堆棧中被其代碼釋放。在這種情況下行爲是不確定的。

因此,釋放一個COM對象的安全方法是從所有訂閱事件中仔細取消訂閱,然後調用Marshal.FinalReleaseComObject()來釋放RCW,並通過這樣做來釋放對象本身。即使你在事件處理程序中這樣做,COM對象也不會立即死亡,因爲如果正確寫入,它可能會在調用時保留其自身的附加引用。

參見:
Runtime-Callable Wrappers
COM-Callable Wrappers
IConnectionPointContainer在不可控制的世界。

相關問題