c# - 我应该如何声明 Microsoft.Office.Interop.Excel.Worksheet 以便我可以在 C# 中关闭它?

标签 c# office-interop com-interop excel-interop

我很难确保我的 COM 对象正在关闭,所以我不会让 EXCEL.EXE 进程在后台运行。我了解到声明的双点和链接是不好的,因为这可能会使 COM 对象悬而未决。

有谁知道如何修复这行代码,以便我可以正确关闭和释放工作表 COM 对象?

worksheet = (Microsoft.Office.Interop.Excel.Worksheet)workbook.Sheets[strName];

编辑:当我完成执行此行以关闭打开的 Excel 对象时,我尝试使用 app.Quit() ,但这不起作用。但是,如果我在此行之前调用它,app.Quit() 会起作用。

最佳答案

首先,为了让 EXCEL.EXE 进程退出,您不必显式释放您使用的所有 COM 对象。当您获得对 COM 对象的另一个引用时,.NET 运行时隐式为您创建的运行时可调用包装器 (RCW) 由 GC 收集,这会释放底层 COM 对象。

您所要做的就是调用 Quit 方法,释放 RCW 引用并让 GC 收集它们。

//This runs the EXCEL.EXE process.
Microsoft.Office.Interop.Excel.Application app = 
    new Microsoft.Office.Interop.Excel.Application();
//This locks the excel file either for reading or writing 
//depending on parameters.
Microsoft.Office.Interop.Excel.Workbook book = app.Workbooks.Open(...);

...

//Explicitly closing the book is a good thing. EXCEL.EXE is alive 
//but the excel file gets released.
book.Close();

//This lets the EXCEL.EXE quit after you release all your references to RCWs
//and let GC collect them and thus release the underlying COM objects. 
//EXCEL.EXE does not close immediately after this though.
app.Quit();
app = null;

其次,如果保留所谓的双点代码行,则不会造成任何内存泄漏。垃圾收集器将收集 RCW 并在某个时候释放 COM 对象,即当它发现正确时。

最后,如果您希望显式释放 RCW 和相应的 COM 对象以不惜一切代价最小化内存压力,您可以在释放对它们的引用后显式调用 GC 来收集 RCW,甚至显式释放底层 COM GC 收集 RCW 之前的对象。不过要小心。最后一种方式让您对之后从未使用过剩余 RCW 的事实负责,否则您将遇到异常。

using Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;

Application app = new Application();
Workbooks books = clsExcelApplication.Workbooks;
Workbook book = books.Open("...");
Sheets sheets = book.Sheets;
Worksheet sheet = sheets["..."];

...

//Trying to be as explicit as we can.
book.Сlose();

//Revese order. Using FinalReleaseComObject is even more dangerous. 
//You might release an object used inside excel
//code which might lead to some dreadful internal exceptions.
int remainingRefCount;
remainingRefCount = Marshal.ReleaseComObject(sheet);
remainingRefCount = Marshal.ReleaseComObject(sheets);
remainingRefCount = Marshal.ReleaseComObject(book);
remainingRefCount = Marshal.ReleaseComObject(books);
app.Quit();
remainingRefCount = Marshal.ReleaseComObject(app);

记住。如果您手动释放 COM 引用,那么 EXCEL.EXE 的生命周期不依赖于 RCW,您可以在需要时取消它们...

sheet = null;
sheets = null;
book = null;
books = null;
app = null;

在最明确的情况下,不要忘记检查 Marshal.ReleaseComObject 的返回。如果它不为零,则除了您刚刚发布的 RCW 之外,还有其他人持有对您的底层 COM 对象的 COM 引用。

关于c# - 我应该如何声明 Microsoft.Office.Interop.Excel.Worksheet 以便我可以在 C# 中关闭它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36844037/

相关文章:

c# - 我如何使用 asp.net 从另一个用户控件调用用户控件的方法?

excel - VB : Error loading type library/DLL.(HRESULT 异常:0x80029C4A(TYPE_E_CANTLOADLIBRARY)

c# - Excel 自动化 Windows 服务

windows - 注册进程外 COM 服务器时是否需要指定 "ThreadingModel"?

c# - 安装包 : Unable to find package 'WebActivator'

c# - 如何让 Visual Studio 中的设计器使用参数化构造函数生成组件

c# - 阅读下面的 xml 显示 c# 中的错误

c# - 在构建服务器上注册 COM 引用的 DLL

c# - 我可以清楚地了解 ReleaseComObject 吗?我可以忽略它吗?

c# - 在运行时动态添加wcf服务的基地址?