2016-05-03 73 views
0

我有一個函數來讀取Excel,然後工作簿和工作表。 但Excel線程永遠不會完成。我嘗試了我在這裏找到的每個解決方案,但都沒有奏效。c#Excel線程沒有完成(FinalReleaseComObject)

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對象問題。

+0

你的應用崩潰在哪一行? – Gusman

+0

我必須閱讀很多Excel文件。因此,代碼每次在「xlApp = new ApplicationClass();」上啓動Excel。我認爲「xlApp.Quit(); Marshal.FinalReleaseComObject(xlApp); xlApp = null;」足以媲美Excel。但Excel永遠不會關閉。因此,應用程序崩潰是因爲在某個時刻,我有近20個EXCEL.EXE進程在後臺運行。 – Delta

+0

FinalReleaseComObject應該不是必需的。您正在使用.net包裝爲Excel。如果你刪除FinalReleaseComObject會發生什麼? – Uwe

回答

1

我有同樣的問題,我用下面的代碼特異性殺傷過程

[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會給你確切的過程,您可以手動殺死。它會從任務管理器中刪除Excel.exe。

1

在我的理解中,如果您使用.NET wrapper對象(如excel interop),則不必顯式釋放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; 
     } 
    } 

} 

至於上不鏈接的計算器問題評論使用兩個點命令。此示例還在我的機器上使用兩個點命令(打開工作簿)。這沒有什麼區別。 Excel被釋放,並且該過程被關閉。用於測試的Excel表是一個標準表,其中有3個字段填入數字。