5

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

我在网上找到了关于这个主题的各种相互矛盾的建议。在我看来,由于 Outlook PIA 总是返回对其接口的新引用作为其方法的返回值,因此没有必要显式释放它。我对吗?

4

8 回答 8

2

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

我个人没有使用过 Microsoft Office PIA,但在大多数情况下,您不必式发布引用。只有当您的应用程序开始锁定其他资源或崩溃时,您才应该开始怀疑悬空引用。

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

于 2008-10-03T14:19:17.330 回答
2

通常,使用 Microsoft Office,您确实需要明确发布您的引用,这可以分两个阶段安全地完成:

(1) 首先通过调用 GC.Collect() 和 GC.WaitForPendingFinalizers() 释放所有不持有命名对象变量的次要对象。(如果涉及的对象可能具有终结器,例如在使用 Visual Studio Tools for Office (VSTO) 时,您需要调用它两次。)

(2) 然后通过在每个对象上调用 Marshall.FinalReleaseComObject() 显式释放您持有命名变量的对象。

就是这样。:-)

在上一篇文章中更详细地讨论了这一点,以及一个代码示例。

于 2008-10-03T15:47:16.700 回答
2

对于 VS 2010,请参阅Marshal.ReleaseComObject 被认为是危险的。

于 2010-08-03T21:14:35.780 回答
1

这里有一些使用托管包装器的好做法..值得一试..

于 2008-10-03T13:53:06.883 回答
0

也许这只是我的迷信,但我决定通过 Marshal.ReleaseComObject() 明确发布 Office PIA,因为当我的应用程序崩溃时,对 Excel 和 Word 的引用保持打开状态。我没有深入挖掘原因(愚蠢的截止日期),但将它们作为我班级的处置模式的一部分发布解决了这个问题。

于 2008-10-03T13:55:24.617 回答
0

如果您希望 Office 应用程序的实例退出,您确实需要这样做,如本文所述。

除了最简单的情况外,很难在所有情况下都做到这一点。

于 2008-10-03T14:57:50.823 回答
0

我的经验表明您必须这样做,否则(至少是 Outlook)应用程序可能根本不会关闭。

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

我在这里发布了一个相关的问题,但我仍然没有明确的答案。一旦我知道更多,我会编辑这篇文章。

于 2008-10-03T18:30:25.247 回答
0

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

于 2008-10-04T05:23:24.353 回答