c# - 发布COM组件




.net outlook (6)

PIA是.NET互操作包装。 这意味着在对象的析构函数(或Dispose - 我不记得)将自动处理其引用计数。 诀窍是一些引用在垃圾收集器被执行之前不会被释放。 这取决于COM对象实例化的内容。 例如,打开数据库游标的COM对象将使这些游标保持在内存中,直到释放这些游标上的引用计数为止。 使用.NET / COM互操作,只有在垃圾回收器执行或者使用Marshal.ReleaseComObject(或FinalReleaseComObject)显式释放引用时才会释放引用。

我个人并没有使用Microsoft Office PIA,但在大多数情况下,您不应该明确地发布引用。 只有当你的应用程序开始锁定其他资源或崩溃,你应该开始怀疑悬挂引用。

编辑:如果遇到了需要清理COM / Interop对象的情况,请使用Marshal.FinalReleaseComObject - 它将引用计数一直设置为零,而不是仅仅递减一个 - 并将对象引用设置为null。 如果你真的想要安全,你可以显式地强制垃圾回收(GC.Collect),但是要小心GC的执行频率,因为它会引起明显的性能下降。

真的有必要从Office PIA发布COM组件,当你不再需要它们时,通过调用Marshal.ReleaseComObject(..)?

我在网上发现了关于这个话题的各种各样的矛盾的建议。 在我看来,由于Outlook PIA总是返回一个新的对其接口的引用,作为从其方法返回的值,所以没有必要明确地释放它。 我对吗?


也许这只是我的迷信,但我决定通过Marshal.ReleaseComObject()明确地发布Office PIA,因为当我的应用程序崩溃时,对Excel和Word的引用保持打开状态。 我没有深入了解为什么(愚蠢的最后期限),但作为我的类的处置模式的一部分释放他们解决了这个问题。


有一个关于.Net / COM互操作的简单规则 - 如果有疑问,总是使用Release()。 :-)



对于Microsoft Office,一般来说,您确实需要明确地发布引用,这可以分两步安全地完成:

(1)首先通过调用GC.Collect(),然后调用GC.WaitForPendingFinalizers(),释放所有未保存命名对象变量的次要对象。 (如果涉及的对象可能有终结器,例如使用Visual Studio Tools for Office(VSTO),则需要调用两次。)

(2)然后通过对每个对象的Marshall.FinalReleaseComObject()的调用明确地释放你持有一个命名变量的对象。

而已。 :-)

在之前的文章中更详细地讨论了这个问题,还有一个代码示例。


我的经验表明,你必须,否则(至少Outlook)的应用程序可能不会关闭。

但是这会打开另一个蠕虫,因为它看起来像RCW是每个进程,因此你可以打破一些其他的插件,这恰好有一个对同一个对象的引用。

我在这里发布了一个相关的问题,但是我还没有明确的答案。 一旦知道更多,我会编辑这个帖子。