如何正确清理 Excel 互操作对象? [英] How do I properly clean up Excel interop objects?

查看:35
本文介绍了如何正确清理 Excel 互操作对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 C# (ApplicationClass) 中使用 Excel 互操作,并将以下代码放在我的 finally 子句中:

I'm using the Excel interop in C# (ApplicationClass) and have placed the following code in my finally clause:

while (System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet) != 0) { }
excelSheet = null;
GC.Collect();
GC.WaitForPendingFinalizers();

尽管这种工作有效,但即使我关闭 Excel,Excel.exe 进程仍然在后台.只有在我的应用程序被手动关闭后才会发布.

Although this kind of works, the Excel.exe process is still in the background even after I close Excel. It is only released once my application is manually closed.

我做错了什么,或者有没有其他方法可以确保正确处理互操作对象?

What am I doing wrong, or is there an alternative to ensure interop objects are properly disposed of?

推荐答案

Excel 没有退出,因为您的应用程序仍然持有对 COM 对象的引用.

Excel does not quit because your application is still holding references to COM objects.

我猜您是在调用 COM 对象的至少一个成员,而没有将其分配给变量.

对我来说,它是我直接使用的 excelApp.Worksheets 对象,而没有将其分配给变量:

For me it was the excelApp.Worksheets object which I directly used without assigning it to a variable:

Worksheet sheet = excelApp.Worksheets.Open(...);
...
Marshal.ReleaseComObject(sheet);

我不知道 C# 在内部为 Worksheets COM 对象创建了一个包装器,它没有被我的代码释放(因为我不知道),这就是为什么Excel 未卸载.

I didn't know that internally C# created a wrapper for the Worksheets COM object which didn't get released by my code (because I wasn't aware of it) and was the cause why Excel was not unloaded.

我在 这个页面,对于C#中COM对象的使用也有一个很好的规则:

I found the solution to my problem on this page, which also has a nice rule for the usage of COM objects in C#:

切勿在 COM 对象中使用两个点.

Never use two dots with COM objects.

<小时>

所以有了这些知识,正确的方法是:


So with this knowledge the right way of doing the above is:

Worksheets sheets = excelApp.Worksheets; // <-- The important part
Worksheet sheet = sheets.Open(...);
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);

验尸报告:

我希望每位读者都非常仔细地阅读 Hans Passant 的这个回答,因为它解释了我和许多其他开发人员偶然发现的陷阱.几年前我写这个答案时,我不知道调试器对垃圾收集器的影响,并得出了错误的结论.为了历史起见,我保持我的答案不变,但请阅读此链接并且不要走两点"的道路:了解 .NET 中的垃圾收集使用 IDisposable 清理 Excel 互操作对象

I want every reader to read this answer by Hans Passant very carefully as it explains the trap I and lots of other developers stumbled into. When I wrote this answer years ago I didn't know about the effect the debugger has to the garbage collector and drew the wrong conclusions. I keep my answer unaltered for the sake of history but please read this link and don't go the way of "the two dots": Understanding garbage collection in .NET and Clean up Excel Interop Objects with IDisposable

这篇关于如何正确清理 Excel 互操作对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆