我在C#(ApplicationClass)中使用Excel互操作,并在finally子句中放置了以下代码:
while (System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet) != 0) { }
excelSheet = null;
GC.Collect();
GC.WaitForPendingFinalizers();
尽管这种方法有效,但即使在我关闭Excel之后,Excel.exe进程仍处于后台。它只在我的应用程序被手动关闭后发布。
我做错了什么,或者是否有其他方法可以确保正确处理互操作对象?
我不敢相信这个问题已经困扰了世界五年。。。。如果您已经创建了应用程序,则需要在删除链接之前先关闭它。
objExcel = new Excel.Application();
objBook = (Excel.Workbook)(objExcel.Workbooks.Add(Type.Missing));
关闭时
objBook.Close(true, Type.Missing, Type.Missing);
objExcel.Application.Quit();
objExcel.Quit();
当您新建一个excel应用程序时,它会在后台打开一个excel程序。您需要在释放链接之前命令该excel程序退出,因为该excel程序不是您直接控制的一部分。因此,如果链接被释放,它将保持开放!
每个人都很好编程~~
这里公认的答案是正确的,但也要注意,不仅需要避免“双点”引用,还需要避免通过索引检索的对象。您也不需要等到程序完成后才能清理这些对象,最好创建函数,以便在可能的情况下,在完成这些对象后立即清理它们。下面是我创建的一个函数,用于分配名为xlStyleHeader的Style对象的一些财产:
public Excel.Style xlStyleHeader = null;
private void CreateHeaderStyle()
{
Excel.Styles xlStyles = null;
Excel.Font xlFont = null;
Excel.Interior xlInterior = null;
Excel.Borders xlBorders = null;
Excel.Border xlBorderBottom = null;
try
{
xlStyles = xlWorkbook.Styles;
xlStyleHeader = xlStyles.Add("Header", Type.Missing);
// Text Format
xlStyleHeader.NumberFormat = "@";
// Bold
xlFont = xlStyleHeader.Font;
xlFont.Bold = true;
// Light Gray Cell Color
xlInterior = xlStyleHeader.Interior;
xlInterior.Color = 12632256;
// Medium Bottom border
xlBorders = xlStyleHeader.Borders;
xlBorderBottom = xlBorders[Excel.XlBordersIndex.xlEdgeBottom];
xlBorderBottom.Weight = Excel.XlBorderWeight.xlMedium;
}
catch (Exception ex)
{
throw ex;
}
finally
{
Release(xlBorderBottom);
Release(xlBorders);
Release(xlInterior);
Release(xlFont);
Release(xlStyles);
}
}
private void Release(object obj)
{
// Errors are ignored per Microsoft's suggestion for this type of function:
// http://support.microsoft.com/default.aspx/kb/317109
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
}
catch { }
}
请注意,我必须将xlBorders[Excel.XlBordersIndex.xlEdgeBottom]设置为一个变量,以清除该变量(不是因为两个点,这两个点指的是不需要释放的枚举,而是因为我所指的对象实际上是一个需要释放的Border对象)。
在标准应用程序中,这种事情并不是真正必要的,因为这些应用程序在清理后会做得很好,但在ASP.NET应用程序中如果您错过了其中的一个,无论您调用垃圾收集器的频率如何,Excel仍将在您的服务器上运行。
编写这段代码时,在监视任务管理器的同时,它需要对细节和许多测试执行进行大量关注,但这样做可以省去在代码页中拼命搜索以查找遗漏的一个实例的麻烦。当在循环中工作时,这一点尤其重要,因为您需要释放对象的每个实例,即使它每次循环都使用相同的变量名。