C#釋放資源

 什麼是資源? .NET 框架中如何訪問資源?算法

所謂的資源就是程序中可利用的數據,譬如:字符串、圖片和任何二進制數據,包括任何類型的文件。數據庫

在面向對象的環境中,每個類型都標識爲某些程序所用的資源,要想使用這些資源,必須爲相應的類型分配必定的內存空間。框架

訪問一個資源須要以下幾個步驟:函數

1)分配內存空間: 調用中間語言(IL)中的newobj指令(使用new操做符時,將產生newobj指令),爲某個特定資源的類型分配必定的內存空間。spa

2) 初始化內存: 一個類型的實例構造器負責這樣的初始化工做。操作系統

3)使用資源: 經過訪問類型成員來使用資源。根據須要會有反覆。線程

4)銷燬資源: 執行清理工做。對象

5)釋放內存: 託管堆上的內存由GC全權負責, 值引用的在棧上的內存會隨着棧空間的消亡而自動消失。繼承

 

1. 什麼是託管資源,非託管資源?接口

託管資源是由CLR全權負責的資源,CLR不負責的資源位非託管資源。 

對於託管資源經過GC自動回收。

對於非託管資源GC管理,經過代碼調用手動進行清除。

 

2. 什麼是垃圾, 什麼是垃圾回收?

Net類型分爲兩大類,一個就是值類型,另外一個就是引用類型。前者是分配在棧上,並不須要GC回收;後者是分配在堆上,所以它的內存釋放和回收須要經過GC來完成,

那麼只有被稱爲垃圾的對象才能被GC回收。也就是說,一個引用類型對象所佔用的內存須要被GC回收,須要先成爲垃圾。

那麼.Net如何斷定一個引用類型對象是垃圾呢,.Net的判斷很簡單,只要斷定此對象或者其包含的子對象沒有任何引用是有效的,那麼系統就認爲它是垃圾。

 

內存的釋放和回收須要伴隨着程序的運行,所以系統爲GC安排了獨立的線程。那麼GC的工做大體是,查詢內存中對象是否成爲垃圾,而後對垃圾進行釋放和回收。

那麼對於GC對於內存回收採起了必定的優先算法進行輪循回收內存資源。

其次,對於內存中的垃圾分爲兩種,一種是須要調用對象的析構函數,另外一種是不須要調用的。

GC對於前者的回收須要經過兩步完成,第一步是調用對象的析構函數,第二步是回收內存,可是要注意這兩步不是在GC一次輪循完成,即須要兩次輪循;相對於後者,則只是回收內存。

 

3. 如何正確的釋放資源?

託管的內存資源,這是不須要咱們操心的,系統已經爲咱們進行管理了。

對於非託管的資源,這裏再重申一下,就是Stream,數據庫的鏈接,GDI+的相關對象,還有Com對象等等這些操做系統資源,須要咱們手動去釋放。

 

如何去釋放,應該把這些操做放到哪裏比較好呢。.Net提供了三種方法,也是最多見的三種,大體以下:

1. 析構函數;

2. 繼承IDisposable接口,實現Dispose方法;

3. 提供Close方法。

 

 

析構函數

Dispose方法

Close方法

意義

銷燬對象

銷燬對象

關閉對象資源

調用方式

不能被顯示調用,會被GC調用

須要顯示調用

或者經過using語句

須要顯示調用

調用時機

不肯定

肯定,在顯示調用或者離開using程序塊

肯定,在顯示調用時