发布COM组件

5

当您不再需要调用Marshal.ReleaseComObject(..)时,是否真的有必要从Office PIA中释放COM组件?

我在网上找到了各种矛盾的建议。 在我看来,由于Outlook PIA始终将其接口作为其方法的返回值返回给新引用,因此不需要显式释放它。 我是对的吗?

8个回答

3

2
PIA是.NET互操作包装器。这意味着在对象的析构函数(或Dispose - 我记不清了)将自动处理其引用计数。问题在于,有些引用直到垃圾收集器执行后才会被释放。这取决于COM对象实例化了什么。例如,打开数据库游标的COM对象将保持这些游标在内存中,直到这些游标的引用计数被释放。使用.NET/COM互操作,这些引用在垃圾收集器执行或您显式释放引用使用Marshal.ReleaseComObject(或FinalReleaseComObject)之前不会被释放。
我个人没有使用过Microsoft Office PIA,但在大多数情况下,您不应该必须显式释放引用。只有当你的应用程序开始锁定其他资源或崩溃时,你应该开始怀疑悬空引用。
编辑:如果遇到需要清理COM/Interop对象的情况,请使用Marshal.FinalReleaseComObject - 它将引用计数减少为零而不仅仅是减少一个,并将对象引用设置为null。如果您确实想要安全,可以显式强制进行垃圾回收(GC.Collect),但小心不要经常进行GC,因为它确实会影响性能。

2
使用Microsoft Office时,通常需要显式释放引用,可以安全地分为两个阶段进行:
(1) 首先通过调用GC.Collect()和GC.WaitForPendingFinalizers()释放所有未使用命名对象变量的次要对象。(如果涉及到具有终结器的对象,比如使用Visual Studio Tools for Office (VSTO)时,则需要调用两次。)
(2) 然后,通过在每个对象上调用Marshall.FinalReleaseComObject()显式释放持有命名变量的对象。
就是这样。 :-)
我在之前的帖子中详细讨论了这个问题,并提供了代码示例。

Mike,你能否对这个进行评论:https://dev59.com/70XRa4cB1Zd3GeqPrGDO - Sunny Milenov

1

这里有一些使用托管包装器的好方法在这里,值得一看。


谢谢,这是一篇好文章。但是,我需要知道是否需要显式释放现有Office PIA中的COM组件,而不是制作自己的包装器。 - Nenad Dobrilovic

0
也许这只是我的迷信,但我决定通过Marshal.ReleaseComObject()显式释放Office PIA,因为当我的应用程序崩溃时,对Excel和Word的引用仍然保持打开状态。我没有深入研究原因(愚蠢的截止日期),但在我的类的dispose模式中释放它们解决了这个问题。

0

如果您想要退出 Office 应用程序的实例,就需要这样做,如this post中所述。

在除了最简单的情况之外,很难做到完全正确。


但是,如果我省略了清理代码,也不会发生什么坏事。在这种情况下,Outlook 甚至会更快地关闭,并且我在网上找到了一些文章,说明释放 Outlook COM 对象并不是必需的。 - Nenad Dobrilovic

0

我的经验表明,否则(至少Outlook),应用程序可能根本无法关闭。

但这又引发了另一个问题,因为看起来RCW是每个进程的,因此您可能会破坏其他一些插件,这些插件恰好引用相同的对象。

我已经发布了一个相关的问题here,但我仍然没有清晰的答案。一旦我知道更多信息,我将编辑此帖子。


0

关于 .Net/COM 互操作有一个简单的规则 - 当你不确定时,总是要释放(Release())。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接