我在 C# ( ApplicationClass) 中使用 Excel 互操作,并在 finally 子句中放置了以下代码:
ApplicationClass
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet) != 0) { } excelSheet = null; GC.Collect(); GC.WaitForPendingFinalizers();
尽管这种方法有效,但Excel.exe即使在我关闭 Excel 后,该过程仍在后台。只有在我的应用程序手动关闭后才会发布。
Excel.exe
我做错了什么,或者是否有其他方法可以确保正确处理互操作对象?
Excel 不会退出,因为您的应用程序仍持有对 COM 对象的引用。
我猜您正在调用 COM 对象的至少一个成员,而没有将其分配给变量。
对我来说,这是我直接使用的 excelApp.Worksheets 对象,而没有将其分配给变量:
Worksheet sheet = excelApp.Worksheets.Open(...); ... Marshal.ReleaseComObject(sheet);
我不知道内部 C# 为 Worksheets COM 对象创建了一个包装器,该包装器没有被我的代码释放(因为我不知道它),这也是 Excel 没有被卸载的原因。
我在这个页面上找到了我的问题的解决方案,它也有一个很好的规则,用于在 C# 中使用 COM 对象:
切勿对 COM 对象使用两个点。
因此,有了这些知识,执行上述操作的正确方法是:
Worksheets sheets = excelApp.Worksheets; // <-- The important part Worksheet sheet = sheets.Open(...); ... Marshal.ReleaseComObject(sheets); Marshal.ReleaseComObject(sheet);
验尸后更新:
我希望每位读者都非常仔细地阅读 Hans Passant 的这个答案,因为它解释了我和许多其他开发人员偶然发现的陷阱。当我几年前写这个答案时,我不知道调试器对垃圾收集器的影响并得出了错误的结论。为了历史,我保持我的答案不变,但请阅读此链接并且 不要 走“两个点”的方式:了解 .NET 中的垃圾收集和使用 IDisposable 清理 Excel 互操作对象