使用EXCEL產生報表,再VB6時我們會使用CreateObject開始,
再以Set Nothing 結束,就OK了~
但在.NET並不是這麼簡單就可以釋放記憶體,
每執行一次,工作管理員又會產生一次EXCEL.EXE
網路上查到許多使用GC.Collect()來強制回收,
也有看到Kill Process的...
但這樣強制系統回收....總覺得這樣好像哪裡不妥,
若不到最後,我想我應該不會使用這方法去強制影響系統的運作,
而且這在Client端程式可以這樣執行,到Server端執行又不行~"~
一開始我還想說是權限問題~測了很久....
想說乾脆執行一次CreateObject,後續使用getObject重複使用該Object就好,結果...
又是Client可以,Server端不行,~"~
查到最後...是有Server.CreateObject 卻沒有 Server.GetObject
之後回歸最原始的方式,
再仔細看微軟的支援頁面,.NET 2.0之後可使用以下程式來回收記憶體
System.Runtime.InteropServices.Marshal.FinalReleaseComObject
我就從每一層結束都做FinalReleaseComObject,
結果發現,只寫以下就可以釋放EXCEL.EXE的記憶體
Dim xlapp As Excel.Application = Server.CreateObject("Excel.Application")
xlapp.Quit()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlapp)
xlapp = Nothing
但只要再中間加上下列開啟檔案....
Dim xlBook As Workbook = xlapp.Workbooks.Open(wkPath & "\sample.xlsx")
xlBook.Close()
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlBook)
xlBook = Nothing
EXCEL.EXE就會出現在工作管理員中屹立不搖...
之後再想到根本,EXCEL的組成元素如下,
Application、Workbooks、Workbook、Worksheet、Range
所以就每一層都SET NEW 用完都做FinalReleaseComObject
每一層都需要正常開始與結束就可以正確釋放記憶體
這樣寫CODE寫得有點複雜,不過記憶體真的可以正常釋放,
只要其中一個環節沒有做到EXCEL.EXE就會在工作管理員中,
範例是讀取現有EXCEL擋,之後修改內容後關閉儲存~
Imports Excel = Microsoft.Office.Interop.Excel
Imports System.Runtime.InteropServices.Marshal
Sub Excel()
Dim xlApp As New Excel.Application
Dim xlBooks As Excel.Workbooks = xlApp.Workbooks
Dim xlBook = xlBooks.Open("D:\sample.xlsx")
Dim xlSheet As Excel.Worksheet = xlBook.ActiveSheet
Dim xlRange As Excel.Range
xlApp.Visible = False
xlApp.DisplayAlerts = False
xlRange = xlSheet.Range("A1")
xlRange.Value = 123
FinalReleaseComObject(xlRange)
FinalReleaseComObject(xlSheet)
xlBook.Save()
xlBook.Close()
FinalReleaseComObject(xlBook)
FinalReleaseComObject(xlBooks)
xlApp.Quit()
FinalReleaseComObject(xlApp)
End Sub
參考資料:http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109&#appliesto
~Shael
留言列表