.NET 运行时何时为 COM 对象保留大于 1 的引用计数?
-
24-09-2019 - |
题
直到最近,我还认为 .NET 运行时在创建 COM 对象时只会将 COM 对象的引用计数增加 1 运行时可调用包装器, ,并且为任何给定的 COM 对象只创建一个这样的运行时可调用包装器。
如果我没记错的话,上面的意思是 Marshal.FinalReleaseComObject 和 Marshal.ReleaseComObject 在实践中做同样的事情。
然而,今天我正在编写一些测试来验证我的代码是否正确释放了 COM 对象。我通过调用所谓释放的对象并检查预期的来做到这一点 InvalidComObjectException
. 事实证明,有些情况是在 a 之后抛出异常的 FinalReleaseComObject
, ,但不是在 ReleaseComObject
.
这是否意味着 .NET 2.0 运行时可以保存多个对 COM 对象的引用?如果是这样,它什么时候这样做?
解决方案
这里有一个额外的间接级别。是的,RCW 在本机 COM 接口指针上保留单个引用计数。但 RCW 也有一个引用计数,每次将 COM 接口指针映射到 RCW 时,它都会递增。如果 COM 方法返回接口指针,则可能会发生这种情况。相应 .NET 包装类的终结器将其递减。
您可以直接通过 Marshal.ReleaseComObject() 修改该引用计数,它像终结器一样将其减一,并通过 Marshal.FinalReleaseComObject() 直接将其清零,保证调用 IUnknown::Release() 方法。他们当然属于“更好地了解你在做什么”类别。出错会产生丑陋且无法调试的“COM 对象与其底层 RCW 分离”异常。
不隶属于 StackOverflow