.NET和COM互操作性:从.NET客户端发布COM

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

是否有必要从.NET客户端调用Marshal.FinalReleaseComObject方法来释放COM对象?


不需要.Net客户端不需要显式释放COM对象。 COM对象将像其他任何.Net对象一样被收集,并且一旦删除了它的所有引用,就会释放它的基础本地句柄。

FinalReleaseComObject明确使用实际上会导致编程错误。 如果代码中的另一个组件仍然引用了COM对象,那么您将从其下拉出本地对象。 这可能会导致运行时故障。


修改的“是”和“否”。

首先,请记住, ReleaseComObject不会自动减少真正的COM对象引用计数。 而是减少内部RCW计数器。 (每次从COM-> NET移动相同的COM对象时,它将使用相同的RCW并将RCW计数器加1。)同样, FinalRelaseComObject也会影响RCW的反作用并有效地将其设置为0。 当RCW计数器变为零时,.NET将减少实际的COM参考计数。

所以, “是”,但是对于这些规则进行了修改

  • 每当一个对象从COM-> NET交叉时,它都应该有ReleaseComObject ,但不是FinalReleaseComObject ,它会被调用。 也就是说,每次对象交叉时应该调用一次,即使它导致引用等于RCW。
  • 对RCW(这只是一个代理包装)的引用数量无关紧要; 只有物体越过边界的时间。 见规则#1。 (控制引用和保留引用很重要,但在这种情况下发生的“最差”是使用“分离的RCW”的例外,这与使用Disposed流无异)。
  • 我说的是上面的规则,而不是FinalReleaseComObject因为RCW对象被缓存在身份代理中,所以使用FinalReleaseComObject会影响你甚至不知道的COM-> NET边界交叉点 ! (这很糟糕,在这一点上,我完全同意JaredPars的回答。)

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

    但是,由于.NET GC非常挑剔且不确定,依靠这种行为意味着对象生命期不受控制。 例如,这可能会在使用Outlook对象模型时导致很多细微的问题。 (它可能不太容易出现其他COM服务器的问题,但OOM在内部搞笑地“缓存”了对象。当不明确控制生命期时,很容易得到“Item has been been modified”异常。)

    在我的代码中,我有一个支持IDisposableComWrapper类。 这允许我传递从COM-> NET获得的RCW对象,并拥有明确的生命周期所有权。 在我的Outlook-Addin开发中,我很少遇到问题(几乎没有,实际上),之后切换到这种方法和众多问题。 “缺点”是需要确定COM-> NET边界,但一旦出现,那么内部的所有生命周期都会被正确处理。

    快乐的编码。

    链接地址: http://www.djcxy.com/p/58211.html

    上一篇: .NET and COM Interoperability : release COM from .NET client

    下一篇: java interscect, union, join, distinct lists with predicate