.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参考计数。
所以, “是”,但是对于这些规则进行了修改 :
ReleaseComObject
,但不是FinalReleaseComObject
,它会被调用。 也就是说,每次对象交叉时应该调用一次,即使它导致引用等于RCW。 我说的是上面的规则,而不是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”异常。)
在我的代码中,我有一个支持IDisposable
的ComWrapper
类。 这允许我传递从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