在 SO 上有很多关于释放 COM 对象和垃圾回收的问题,但我找不到具体解决这个问题的内容。
当释放 COM 对象(在这种情况下特别是 Excel Interop)时,我应该以什么顺序释放引用和调用垃圾回收?
在一些地方(比如 here )我看到了这个:
Marshall.FinalReleaseComObject(obj);
GC.Collect();
GC.WaitForPendingFinalizers();
而在其他(例如 here)中:
GC.Collect();
GC.WaitForPendingFinalizers();
Marshall.FinalReleaseComObject(obj);
或者这不重要,我什么都不担心?
最佳答案
Marshal.FinalReleaseComObject() 释放底层 COM 接口(interface)指针。
GC.Collect() 和 GC.WaitForPendingFinalizers() 导致调用 COM 包装器的终结器,它调用 FinalReleaseComObject()。
所以没有意义的是两种方式。选择一个或另一个。
显式调用 FinalReleaseComObject() 的问题在于,只有当您为所有 接口(interface)指针调用它时,它才会起作用。如果您只错过其中一个,Office 程序将继续运行。这非常很容易做到,尤其是 C# 版本 4 中允许的语法糖使它成为可能。类似 range = sheet.Cells[1, 1]
的表达式,在 Excel 互操作代码中非常常见。那里有一个隐藏的 Range 接口(interface)引用,您永远不会将其显式存储在任何地方。所以你也不能释放它。
这不是 GC.Collect() 的问题,它可以看到它们。然而,它也并非完全没有问题,它只会在您的程序不再引用该接口(interface)时收集并运行终结器。这绝对是你的第二个片段有什么问题。当你调试你的程序时往往会出错,调试器将本地对象引用的生命周期延长到方法的末尾。还有你看着 Taskmgr 大喊“去死!”的时候
GC.Collect() 的常用建议也适用于此。保持程序运行并执行工作。正常的事情会发生,您将触发垃圾收集并释放 COM 包装器。 Office 程序将退出。它不会立即发生,它最终会发生。
关于c# - 应该以什么顺序释放 COM 对象和垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13572004/