使用 IDisposable 清理 Excel 互操作對象
在我公司,發布 Excel 互操作對象的常用方法是使用
IDisposable以下方式:Public Sub Dispose() Implements IDisposable.Dispose If Not bolDisposed Then Finalize() System.GC.SuppressFinalize(Me) End If End Sub Protected Overrides Sub Finalize() _xlApp = Nothing bolDisposed = True MyBase.Finalize() End Subwhere
_xlApp在建構子中通過以下方式創建:Try _xlApp = CType(GetObject(, "Excel.Application"), Excel.Application) Catch e As Exception _xlApp = CType(CreateObject("Excel.Application"), Excel.Application) End Try客戶端使用
using-statement執行有關 excel 互操作對象的程式碼。我們完全避免使用兩點規則。現在我開始研究如何發布 (Excel) Interop Objects 以及我發現的幾乎所有關於它的討論,例如如何正確清理 excel interop objects或Release Excel Objects are using most
Marshal.ReleaseComObject(),但沒有一個使用IDisposable介面。我的問題是:使用
IDisposable互動來發布 excel 互操作對像有什麼缺點嗎?如果是這樣,這些缺點是什麼。
使用 IDisposable Interace 有什麼缺點嗎
當然,它什麼也沒做。使用Using或呼叫 Dispose() 從來都不是將變數設置為 Nothing 的合適方法。這就是您的程式碼所做的一切。
我們完全避免使用兩點規則。
隨意繼續忽略它,這是胡說八道,只會引起悲傷。部落格作者的隱含斷言是,這樣做會迫使程序員使用變數來儲存 xlApp.Workbooks 的值。所以他以後會有一個戰鬥的機會,不要忘記呼叫releaseObject()。但是還有更多語句可以生成不使用點的介面引用。像 Range(x,y) 這樣的東西,那裡有一個隱藏的 Range 對象引用,你永遠看不到。必須同時儲存它們只會產生令人難以置信的複雜程式碼。
僅僅忽略一個就足以完全無法完成工作。完全無法調試。這是 C 程序員必須編寫的那種程式碼。並且經常慘遭失敗,大型 C 程序經常洩漏記憶體,並且他們的程序員花費大量時間來查找這些洩漏。當然不是 .NET 方式,它有一個垃圾收集器來自動執行此操作。它永遠不會出錯。
麻煩的是,處理工作有點慢。非常設計。沒有人注意到這一點,除了這種程式碼。您可以看到垃圾收集器沒有執行,您仍然看到 Office 程序正在執行。當您編寫 xlapp.Quit() 時它並沒有退出,它仍然存在於任務管理器的程序選項卡中。他們想要發生的事情是當他們這麼說時它就退出了。
這在 .NET 中很有可能,您當然可以強制 GC 完成工作:
GC.Collect() GC.WaitForPendingFinalizers()繁榮,每個Excel 對象引用都會自動釋放。無需自己儲存這些對象引用並顯式呼叫 Marshal.ReleaseComObject(),CLR 會為您完成。它永遠不會出錯,它不使用或不需要“兩點規則”,並且可以輕鬆找到那些隱藏的介面引用。
然而,重要的是你把這段程式碼放在哪裡**。**大多數程序員把它放在錯誤的地方,使用那些 Excel 介面的方法。這很好,但在調試程式碼時不起作用,這是一個在這個答案中解釋的怪癖。在部落格作者的程式碼中,正確的做法是將程式碼移動到一個小輔助方法中,我們稱之為 DoExcelThing()。像這樣:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click DoExcelThing() GC.Collect() GC.WaitForPendingFinalizers() '' Excel.exe no longer running anymore at this point End Sub請記住,這實際上只是一個調試工件。程序員只是討厭不得不使用任務管理器來殺死殭屍 Excel.exe 實例。當他們停止調試器時殭屍化,阻止程序正常退出並收集垃圾。這是正常的。當您的程序因任何原因在生產中當機時,也會發生這種情況。把你的精力放在它所屬的地方,從你的程式碼中消除錯誤,這樣你的程序就不會死掉。GC 不需要更多的幫助。