c#Excel线程没有完成(FinalReleaseComObject)

我有一个函数来读取一个Excel,然后工作簿和工作表。 但Excel线程永远不会完成。 我尝试了我在这里find的每个解决scheme,但没有工作。

在任务pipe理器上的Excel线程堆栈,并在那个时候,我的应用程序崩溃,因为Excel停止工作。

public static object[,] ReadFile(string filepath, string sheetname) { Application xlApp = null; Workbooks wks = null; Workbook wb = null; object[,] values = null; try { xlApp = new ApplicationClass(); wks = xlApp.Workbooks; wb = wks.Open(filepath, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing); Worksheet sh = (Worksheet)wb.Worksheets.get_Item(sheetname); values = sh.UsedRange.Value2 as object[,]; System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sh); sh = null; } catch (Exception ex) { throw new Exception(string.Format("Sheet \"{0}\" does not exist in the Excel file", sheetname)); } finally { if (wb != null) { wb.Close(false); Marshal.FinalReleaseComObject(wb); wb = null; } if (wks != null) { wks.Close(); Marshal.FinalReleaseComObject(wks); wks = null; } if (xlApp != null) { // Close Excel. xlApp.Quit(); Marshal.FinalReleaseComObject(xlApp); xlApp = null; } } return values; } 

也许我不会按照正确的顺序来做事情,或者我理解错误的COM对象问题。

我有同样的问题,我用下面的代码专门杀死进程

 [DllImport("user32.dll")] static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId); Process GetExcelProcess(Excel.Application excelApp) { int id; GetWindowThreadProcessId(excelApp.Hwnd, out id); return Process.GetProcessById(id); } 

这种方法GetExcelProcess会给你你可以手动杀死的确切过程。 它会从任务pipe理器中删除Excel.exe。

在我的理解中,如果你使用像.net interop这样的.NET包装对象,就不需要明确地释放com对象。 如果excel仍然存在,那么我会查找处理中的错误,因为可能会遗留下一些东西。
在下面的示例中,当涉及到第一个console.ReadLine时,excel进程已经停止。 如果不立即停止尝试打回车启动GC。

以下为我和Excel的作品停止。
我用了:
.NET Framework 4.5.2
Microsoft.Office.Interop.Excel 1.7.0.0
Excel 2010
Windows 7的

 using System; using Microsoft.Office.Interop.Excel; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine("Go"); var t = ReadFile(@"<filename>", "<sheetname>"); Console.WriteLine("1"); Console.ReadLine(); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Console.ReadLine(); } public static object[,] ReadFile(string filepath, string sheetname) { Application xlApp = null; Workbooks wks = null; Workbook wb = null; object[,] values = null; try { xlApp = new Application(); wks = xlApp.Workbooks; wb = wks.Open(filepath); Worksheet sh = (Worksheet)wb.Worksheets.get_Item(sheetname); values = sh.UsedRange.Value2 as object[,]; //System.Runtime.InteropServices.Marshal.FinalReleaseComObject(sh); //sh = null; } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(string.Format("Sheet \"{0}\" does not exist in the Excel file", sheetname)); } finally { if (wb != null) { wb.Close(false); //Marshal.FinalReleaseComObject(wb); wb = null; } if (wks != null) { wks.Close(); //Marshal.FinalReleaseComObject(wks); wks = null; } if (xlApp != null) { // Close Excel. xlApp.Quit(); //Marshal.FinalReleaseComObject(xlApp); xlApp = null; } } return values; } } } 

作为对不使用两个点命令链接的stackoverflow问题的评论。 这个示例在我的机器上也有两个点命令(打开工作簿)。 这没有什么区别。 Excel被释放,并且该过程被closures。 用于testing的excel表单是一个标有3个字段填充数字的表单。