.NET 和 COM 互操作性:从 .NET 客户端释放 COM

.NET and COM Interoperability : release COM from .NET client(.NET 和 COM 互操作性:从 .NET 客户端释放 COM)

本文介绍了.NET 和 COM 互操作性:从 .NET 客户端释放 COM的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个 COM 对象(非托管)和 .NET 客户端.

Assume I have a COM object (unmanaged) and .NET Client.

是否需要从 .NET 客户端调用 Marshal.FinalReleaseComObject 方法才能释放 COM 对象?

Is it necessary to call from the .NET client Marshal.FinalReleaseComObject method in order to release the COM object?

推荐答案

修改是"和否".

首先,请记住 ReleaseComObject 不会自动减少真正的 COM 对象引用计数.相反,它会减少内部 RCW 计数器.(每次 same COM 对象从 COM->NET 移出时,它都会使用 same RCW 并将 RCW 计数器加一.)同样,FinalRelaseComObject 也会影响 RCW 计数器并有效地将其设置为 0".当 RCW 计数器变为零时,.NET 将减少 actual COM ref-count.

First off, bear in mind that ReleaseComObject does not automatically decrease the real COM object ref-count. Rather it decreases the internal RCW counter. (Every time the same COM object is moved from COM->NET it will use the same RCW and increment the RCW counter by one.) Likewise, FinalRelaseComObject also affects the RCW counterand effectively "sets it to 0". It is when the RCW counter goes to zero that .NET will decrease the actual COM ref-count.

所以,是",但根据这些规则进行了修改:

So, "yes", but modified for these rules:

  1. 每次一个对象从 COM->NET 交叉它应该ReleaseComObject但不是 FinalReleaseComObject,对其进行调用.也就是说,每次对象交叉时都应该调用它一次即使它导致引用等于 RCW.
  2. 对 RCW(只是一个代理包装器)的引用数量无关紧要;只有物体越过边界的次数.参见规则#1.(控制引用和谁保留它们很重要,但在这种情况下发生的最坏情况"是使用分离的 RCW"的一个例外,这与使用 Disposed 流没有什么不同.)
  1. Every time an object cross from COM->NET it should have ReleaseComObject, but not FinalReleaseComObject, invoked upon it. That is, it should be invoked once for each time the object crosses, even if it results in a reference-equals RCW.
  2. The number of references to the RCW (which is just a proxy wrapper) do not matter; only the times the object has crossed the boundary. See rule #1. (It is important to control references and who keeps them, but the "worst" that happens in this case is an exception from using a "detached RCW" which is no different than using a Disposed stream.)

我说上面的规则和不是 FinalReleaseComObject 因为RCW对象缓存在一个身份代理中,所以使用FinalReleaseComObject 会影响你甚至不知道的 COM->NET 边界交叉!(这很糟糕,在这一点上,我完全同意 JaredPars 的回答.)

I say the rules above and not FinalReleaseComObject because the RCW objects are cached in an identity proxy, so using FinalReleaseComObject will affect COM->NET boundary crossings you didn't even know about! (This is bad and, on this point, I entirely agree with JaredPars answer.)

否",当一个RCW被回收时(终结器被调用),它会自动释放"COM引用(有效地调用FinalReleaseComObject 本身).请记住,由于只有一个 RCW 对象,这意味着只要在 .NET 中有对它的引用,它就永远不会被回收.如果回收 RCW,则 没有问题,因为从上面看,不再有对所述 RCW 的引用,因此 .NET 知道它可以将 COM 引用计数减少一(这可能会导致 COM要销毁的对象).

And "no" in that, when an RCW is reclaimed (the finalizer is called), it will automatically "release" the COM reference (effectively call FinalReleaseComObject on itself). Remember that since there is only one RCW object this means that it will never be reclaimed as long as there is a reference to it in .NET. If the RCW is reclaimed there is no problem because, from above, there are no more references to said RCW and thus .NET knows it can decrease the COM ref-count by one (which may cause the COM object to be destroyed).

但是,由于 .NET GC 是挑剔的且非确定性,因此依赖此行为意味着对象的生命周期不受控制.例如,在使用 Outlook 对象模型时,这可能会导致许多微妙的问题.(其他 COM 服务器可能不太容易出现问题,但 OOM 会在内部对对象进行有趣的缓存".如果不明确控制生命周期,很容易得到项目已被修改"异常.)

However, since the .NET GC is finicky and non-deterministic, relying on this behavior means that object-lifetimes are not controlled. This can cause many subtle issues when working with the Outlook Object Model, for instance. (It may be less prone to issues with other COM servers, but the OOM does funny "caching" of objects internally. It is easy to get a "Item has already been modified" exception when not controlling lifetimes explicitly.)

在我的代码中,我有一个支持 IDisposableComWrapper 类.这使我可以传递从 COM->NET 获得的具有明确生命周期所有权的 RCW 对象.在切换到这种方法后,我在 Outlook-Addin 开发中遇到的问题非常少(实际上几乎没有),并且之前有许多问题.缺点"是需要确定 COM->NET 边界,但一旦确定,那么内部所有生命周期都得到正确处理.

In my code I have a ComWrapper class that supports IDisposable. This allows me to pass around RCW objects obtained from the COM->NET with clear lifetime ownership. I have had very few issues (almost none, actually) in my Outlook-Addin development after switching to this approach and numerous issues before hand. The "downside" is that COM->NET boundary needs to be determined, but once that is, then internally all the lifetimes are correctly handled.

编码愉快.

这篇关于.NET 和 COM 互操作性:从 .NET 客户端释放 COM的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本文标题为:.NET 和 COM 互操作性:从 .NET 客户端释放 COM

基础教程推荐