当您不再需要COM组件时,真的有必要通过调用Marshal.ReleaseComObject(..)来从Office PIA中释放它们吗?
我在网上找到了关于这个话题的各种相互矛盾的建议。在我看来,由于Outlook PIA总是将对其接口的新引用作为其方法的返回值返回,因此没有必要显式释放它。我说的对吗?
发布于 2008-10-03 15:47:17
通常,对于Microsoft Office,您确实需要显式释放引用,这可以分两个阶段安全地完成:
(1)首先通过调用GC.Collect(),然后调用GC.WaitForPendingFinalizers(),释放您没有持有命名对象变量的所有次要对象。(如果所涉及的对象可能具有终结器,则需要调用此函数两次,例如在使用Visual Studio Tools for Office (VSTO)时。)
(2)然后通过在每个对象上调用Marshall.FinalReleaseComObject()来显式释放您持有已命名变量的对象。
就这样。:-)
我在 in a previous post中更详细地讨论了这一点,并提供了一个代码示例。
发布于 2008-10-03 14:19:17
PIA是.NET互操作包装器。这意味着在对象的析构函数(或Dispose --我记不清了)中将自动处理它的引用计数。诀窍在于,在执行垃圾收集器之前,某些引用不会被释放。这取决于COM对象实例化的内容。例如,打开数据库游标的COM对象将使这些游标在内存中保持活动状态,直到释放这些游标上的引用计数。使用.NET/COM互操作,直到垃圾回收器执行或您使用Marshal.ReleaseComObject (或FinalReleaseComObject)显式释放引用时,才会释放引用。
我个人没有使用过Microsoft Office PIA,但在大多数情况下,您不应该显式发布这些引用。只有当您的应用程序开始锁定其他资源或崩溃时,您才应该开始怀疑悬空引用。
编辑:如果您遇到确实需要清除COM/互操作对象的情况,请使用Marshal.FinalReleaseComObject -它将引用计数一直取为0,而不是只减1-并将对象引用设置为null。如果您真的希望安全,可以显式地强制执行垃圾收集(GC.Collect),但要注意不要太频繁地执行GC,因为它确实会引起明显的性能影响。
发布于 2010-08-04 05:14:36
对于VS2010,请参阅Marshal.ReleaseComObject Is Considered Dangerous。
https://stackoverflow.com/questions/166962
复制相似问题