直到最近,我相信.NET运行时只会在创建runtime-callable wrapper时将COM对象的引用计数增加1,并且只为任何给定的COM对象创建一个这样的运行时可调用包装器。 / p>
如果我没有弄错的话,上述意味着Marshal.FinalReleaseComObject和Marshal.ReleaseComObject在实践中做同样的事情。
但是,今天我正在编写一些测试来验证我的代码是否正确释放了COM对象。我这样做是通过调用所谓的释放对象并检查预期的InvalidComObjectException
。 事实证明,有些情况会在FinalReleaseComObject
后抛出异常,但不会在ReleaseComObject
之后抛出。
这是否意味着.NET 2.0运行时可以包含多个COM对象的引用?如果是这样,它什么时候这样做?
答案 0 :(得分:5)
这里有一个额外的间接水平。是的,RCW在本机COM接口指针上保留单个引用计数。但RCW也有引用计数,每次COM接口指针映射到RCW时它都会递增。如果COM方法返回接口指针,可能会发生这种情况。相应的.NET包装类的终结器会减少它。
你可以直接通过Marshal.ReleaseComObject()来修改引用计数,它会像终结器一样递减它,而Marshal.FinalReleaseComObject()将它拉到零,保证IUnknown :: Release()方法被调用。他们当然属于“更清楚你正在做什么”的类别。出错会产生丑陋且不可剔除的“COM对象与其底层RCW分离”的异常。