2012-02-08 24 views
2

我有這樣一段代碼用於從Excel單元讀取:Excel對象不獲取設置有時

public T GetValue<T>(string testsheet, string range) 
    { 
     Application excelApplication = null; 
     Workbooks workBooks    = null; 
     Workbook activeWorkBook   = null; 
     Worksheet activeWorkSheet  = null; 

     try 
     { 
      excelApplication = new Application(); 
      workBooks   = excelApplication.Workbooks; 
      activeWorkBook  = workBooks.Open(workBook); 

      activeWorkSheet  = activeWorkBook.ActiveSheet; 
      var cells   = activeWorkSheet.get_Range(range); 
      return cells.Value2; 

     } 
     catch (Exception theError) 
     { 
      Console.WriteLine(theError.Message); 
      throw theError; 
     } 
     finally 
     {   
      ReleaseComObject(activeWorkSheet); 
      ReleaseComObject(activeWorkBook); 
      ReleaseComObject(workBooks); 
      ReleaseComObject(excelApplication); 
     }    
    } 

另外我有這設定值對小區的設定值以下方法:

public void SetValue<T>(string testsheet, string range, T value) 
    { 
     Application excelApplication = null; 
     Workbooks workBooks = null; 
     Workbook activeWorkBook = null; 
     Worksheet activeWorkSheet = null; 

     try 
     { 
      excelApplication = new Application(); 
      workBooks = excelApplication.Workbooks; 
      activeWorkBook = workBooks.Open(workBook); 

      activeWorkSheet = activeWorkBook.ActiveSheet; 
      var cells = activeWorkSheet.get_Range(range); 
      cells.Value2 = value; 
      activeWorkBook.Save();    
     } 
     catch (Exception theError) 
     { 
      Console.WriteLine(theError.Message); 
      throw theError; 
     } 
     finally 
     { 
      if (activeWorkBook != null) 
       activeWorkBook.Close(); 

      ReleaseComObject(excelApplication); 
      ReleaseComObject(workBooks); 
      ReleaseComObject(activeWorkBook); 
      ReleaseComObject(activeWorkSheet);             
     }   
    } 

這裏是我的ReleaseComObject的:

private static void ReleaseComObject<T>(T comObject) where T : class 
    { 
     if (comObject != null) 
      Marshal.ReleaseComObject(comObject); 
    } 

我寫了一個測試,以確保Excel對象是properl ý設置如下:

[Test] 
    public void Should_dispose_excel_objects_created_after_io_operation() 
    { 
     var expected = Process.GetProcesses().Count(process => process.ProcessName.ToLower() == "excel"); 

     var automationClient = new ExcelAutomation.ExcelAutomationClient(ExcelSheet); 

     automationClient.SetValue("Sheet1", "A1", 1200); 
     automationClient.GetValue<double>("Sheet1", "A1"); 

     var actual = Process.GetProcesses().Count(process => process.ProcessName.ToLower() == "excel"); 

     actual.Should().Be(expected, "Excel workbook is not disposed properly. There are still excel processess in memory"); 
    } 

此測試passess如果我只調用setValue方法,但是在調用的GetValue它失敗。但是我可以在taskmanager中看不到Excel.exe。任何想法爲什麼發生這種情況?我的GetValue函數有問題嗎?

+0

我相信'get_Range'返回一個COM對象,所以你應該釋放,太。雖然,你在你的兩種方法中調用它。 – BACON 2012-02-08 00:20:52

+0

它與處置沒有任何關係。您正在編寫C代碼,手動管理內存。產生不可避免的錯誤,「泄漏」內存。您沒有爲* cells *對象引用調用ReleaseComObject()。只是不要寫這樣的代碼,沒有意義。垃圾收集器已經知道如何做到這一點。如果你想由於某種原因而急於調用GC.Collect()。只要你有一個很好的理由。 – 2012-02-08 00:30:58

+0

如果你比較兩種方法,我做的事情幾乎是一樣的。如果我不調用ReleaseComObject,則Excel實例在內存中不存在。只有在呼籲它消失之後。即使在這種情況下,它也會消失,但是測試沒有通過。 – Mike 2012-02-08 00:35:47

回答

0

當你完成處置的對象,請使用

GC.Collect(); 

這是我如何處置我的Excel對象

 private void releaseObject(object obj) 
    { 
     try 
     { 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); 
      obj = null; 
     } 
     catch (Exception ex) 
     { 
      obj = null; 
      MessageBox.Show("Exception Occured while releasing object " + ex.ToString()); 
     } 
     finally 
     { 
      GC.Collect(); 
     } 
    } 
+0

你得到它的工作? – Andrew 2012-03-08 18:24:10

相關問題