繁体   English   中英

我应该如何声明一个Microsoft.Office.Interop.Excel.Worksheet,以便可以在C#中将其关闭?

[英]How should I declare a Microsoft.Office.Interop.Excel.Worksheet so I can close it in C#?

我很难确保我的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引用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM