我在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 Interop对象