非託管資源

非託管資源
    對於非託管資源,您在應用程序中使用完這些非託管資源之後,必須顯示的釋放他們.

     垃圾回收器不知道如何釋放非託管的資源(例如文件旬柄、網絡連接和數據庫連接)。託管類在封裝對非託管資源的直接或間接引用時,需要制定專門的規則,確保非託管的資源在回收類的一個實例時釋放。

      在定義一個類時,可以使用兩種機制來自動釋放非託管的資源。這些機制常常放在一起實現,

因爲每種機制都爲問題提供了略爲不同的解決方法。這兩種機制是:

     · 聲明一個析構函數(或終結器),作爲類的一個成員

     · 在類中實現system.IDisposable 接口

 析構函數

     在C#中的析構函數時,在底層的.net體系結構中,這些函數稱爲終結器.在C#定義析構函數時,編譯器發送給程序集的實際上是Finalizer()方法。

     但由於使用C#垃圾回收器的工作方式,無法確定C#對象的析構函數何時執行。所以,不能在析構函數中放置需要在某一時刻運行的代碼,也不應使用能以任意順序對不同類的實例調用的析構函數。如果對象佔用了寶貴而重要的資源,應儘快釋放這些資源,此時就不能等待垃圾回收器來釋放了。

另一個問題是C#析構函數的實現會延遲對象最終從內存中刪除的時間。沒有析構函數的對象會

在垃圾回收器的一次處理中從內存中刪除,但有析構函數的對象需要兩次處理才能銷燬:第一次調用析構函數時,沒有刪除對象,第二次調用才真正刪除對象。另外,運行庫使用一個線程來執行所有對象的Finalize()方法。如果頻繁使用析構函數,而且使用它們執行長時間的清理任務,對性能的影響就會非常顯著。

 system.IDisposable 接口

實現代碼如下:

c1ass MyClass: IDisposable

{

Public void Dispose()

(

// implementation

)

)

Dispose()方法的實現代碼顯式地釋放由對象直接使用的所有非託管資源,並在所有也實現
IDisposable 接口的封裝對象上調用Dispose()方法。這樣,Dispose()方法爲何時釋放非託管資源提供
了精確的控制。

Dispose()方法有第二個protected重載方法,它帶一個布爾參數,這是真正完成清理工作的方法。Dispose(bool)方法由析構函數和IDisposable.Dispose()方法調用。這種方式的重點是確保所有的清理代碼都放在一個地方。

傳遞給Dispose(bool)方法的參數表示Dispose(bool)方法是由析構函數調用,還是由IDisposable.

Dispose(bool)方法調用——Dispose(bool)方法不應從代碼的其他地方調用,其原因是:

● 如果使用者調用IDisposable.Dispose()方法,該使用者就指定應清理所有與該對象相關的資

源,包括託管和非託管的資源。

● 如果調用了析構函數,原則上所有的資源仍需要清理。但是在這種情況下,析構函數必須由垃圾回收器調用,而且用戶不應試圖訪周其他託管的對象,因爲我們不再能確定它們的狀態了。在這種情況下,最好清理己知的非託管資源,希望任何引用的託管對象還有析構函數,這些析構函數執行自己的清理過程。

isDisposed成員變量表示對象是否己被清理,並確保不試圖多次清理成員變量。


最常見的一類非託管資源就是包裝操作系統資源的對象,例如文件,窗口或網絡連接,對於這類資源雖然垃圾回收器可以跟蹤封裝非託管資源的對象的生存期,但它不瞭解具體如何清理這些資源。還好.net Framework提供了Finalize()方法,它允許在垃圾回收器回收該類資源時,適當的清理非託管資源。如果在MSDN Library 中搜索Finalize將會發現很多類似的主題,這裏列舉幾種常見的非託管資源:ApplicationContext,Brush,Component,ComponentDesigner,Container,Context,Cursor,FileStream,Font,Icon,Image,Matrix,Object,OdbcDataReader,OleDBDataReader,Pen,Regex,Socket,StreamWriter,Timer,Tooltip 等等資源。可能在使用的時候很多都沒有注意到





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章