国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C#垃圾回收

2019-11-17 02:16:55
字體:
來源:轉載
供稿:網友

C#垃圾回收

析構方法:

我們知道引用類型都有構造方法(constructor),相對應的也有一個析構方法(destructor).顧名思義,構造方法,就是在創建這個對象時,要執行的方法。例如,我們可以通過構造方法,

初始化字段。析構方法,就是當這個對象被垃圾回收后(garbage collected,我們稱回收對象內存為垃圾回收 garbage collection),要執行的方法。關于析構方法,需要大家注意的是,垃圾回收一個對象,并不是析構方法完成的(下面會講到垃圾回收的工作原理),析構方法只有在對象被垃圾回收后才執行。也就是說,析構方法對于一個對象來講,不是必須的。很多時候,如果加上它,反而不好(下面講garbage collector怎樣工作時,就會明白不好的原因)。

既然垃圾回收不歸析構方法負責,那么它有什么用呢?因為垃圾回收是CLR自動執行的,CLR只能處理受管理資源(managed resource),那些不受管理資源(unmanaged resource)就需要我們

自己去處理了。例如文件讀取(file stream),當對象結束時,我們需要把文件流關掉。關掉文件流的代碼,就要在析構方法中。也就是說,析構方法的用處,在處理不受管理資源時用處比較大。 看個例子:

class FilePRocessor{     FileStream file=null;
public FileProcess(string fileName){     this.file=file.OpenRead(fileName); //open file for reading}~FileProcess()    //析構方法與構造方法很相似,不同的是析構方法要加一個~{     this.file.Close(); //close file}}

file對象,是CRL垃圾回收,當file被垃圾回收后,運行析構方法FileProcess,此時我們將非管理資源關掉。this.file.Close().

這里有幾條對析構方法的限制:

1.只有引用類型才可以有析構方法。

struct MyStruct(){     ~MyStruct(){....}//結構是值類型,所以不能有析構方法       }

2.不能對析構方法提供訪問修飾符.

public ~FileProcessor(){};//錯誤的

3.析構方法不可以有參數.

~FileProcessor(int param){....// //錯誤的};

之所以會有這三條限制,是因為析構方法只能由CLR調用,自己不可以調用。因為,你不知道引用對象什么時候被垃圾回收了,只有對象被垃圾回收了,程序才會自己調用析構方法。

在內部,程序會將我們寫的析構方法,轉換一下。例如:

class FileProcessor{    ~fileProcessor(){...}   //析構方法}class FileProcessor{ protected override void Finalize(){      try{           }finally{      base.Finalize();      //CLR會將析構方法轉變成這個        } } }

我們把執行析構方法的過程,稱為結束(finalization,或終結。)

垃圾回收機制(garbage collector)

我們上邊提到,回收內存空間,回收不用的引用類型對象的過程稱為垃圾回收(garbage collection).這個過程是由CLR通過Garbage collector這樣一個機制去運行的。

當我們在程序中創建變量,會在內存中開辟一段空間。電腦的內存不是無限大的,我們需要在變量超越定義的范圍(程序不再需要這個變量了)時,對它所占的內存進行管理,處理這些內存。當變量不再被使用時,需要把內存回收。值類型變量回收內存,非常簡單。

當它超出定義的范圍時就會自動被毀掉,被占的內存也會自動回收。超出定義的范圍,指的是當它不再被使用,不能再被使用。引用類型變量回收內存,比較麻煩。例如:

fileProcessor myFp=new fileProcessor();fileProcessor referenceToMyFp=myFp;

想一下這種情況,myFp對象已經超出定義的范圍。此時我們去回收內存,要把myFp引用堆上的內存回收。可是,恰恰此時,referenceToMyFp還在引用準備回收的內存,如果此時把內存回收,當程序運行referenceToMyFp時,程序就會出錯。所以,只用當所有引用對象都超出定義的范圍時,也就是都不再使用時,才可以去回收這些對象引用的內存。確保程序中這些指向同一塊兒的引用對象全部不再使用,是很困難,很復雜的.所以C#設計者,把處理引用類型回收內存的工作,交給了CLR(Common language running).CLR利用garbage collector機制,來處理這些事情。

垃圾回收機制工作原理

garbage collector在自己的線程中工作,在特定的時間執行。一般,當程序運行到一個方法的最后時,就會工作。它工作時,其他線程就會暫時停止工作。因為,garbage collector可能會移除或者更新對象引用。

1.garbage collector會創建一張表,表里存放所有的可得到對象(reachable objects,.可得到對象,說白了就是指那些還在使用,不能回收內存的對象。)。

2.檢查一下那些不可得到對象(unreachable objects,就是那些超出定義范圍,需要回收內存的對象),看看他們是否有析構方法。(destructor),如果有,就把這些對象放入一個叫做

freachable queue的隊列里。

3.把那些不可得到對象,且沒有析構方法的對象所指向的內存地址回收。它是通過將那些可得對象在堆上的地址下移,這樣堆上面就留出了可用的內存。此時,garbage collector也會更新堆

上的引用地址。(因為,地址有變化)。

4.此時,程序中其他的線程恢復工作。

5.garbage collector 通過調用自己的Finalize方法來結束不可得到對象,且有析構方法的對象。(前面我們講了,析構方法不是必須的,有時候會給程序帶來復雜,累贅。如果,沒有析構方法,當

CLR運行Garbage collector時,第五步就可以省去)。

資源管理

有些資源很稀缺,稀缺到不能等到CLR去調用析構方法去處理。例如database connections,file handles.此時,我們就需要寫一個dispose方法,手動去處理資源。(dispose可以換成任何名

字,這里只是舉個例子)。例如:

TextReader reader=new StreamReader(filename);string line;while((line=reader.ReadLine())!=null){     Console.WriteLine(line);}reader.Close();

這里,Close就是一個dispose方法,手動去關掉文件流。但是,這樣有個問題,當出現異常時,有可能導致reader.Close()不被執行,這樣資源一直被占用。所以,我們要改寫成:

TextReader reader=new StreamReader(filename);try{    string line;    while((line=reader.ReaderLine())!=null){      Console.WriteLine(line);}}finally{   reader.Close();}

這樣無論如何,reader.Close()都會被執行,資源都會被釋放。不過即便改寫成這樣,也不是最完美的。因為,當我們執行完finally塊兒內的代碼,也就是在try finally之后,我們有可能

無意中使用reader對象,就是釋放掉資源后的reader對象。此時,我們可以用using 語句來解決這些不足。我們將上面的代碼改成using之后:

using(TextReader reader=new StreamReader(filename)){    string line;    while((line=reader.ReadLine())!=null){        Console.Writle(line);}}

執行完using之后,資源自動釋放,越過using范圍,對象不能用。一個對象如果要被支持使用using,該對象必須實現IDispose接口。

我們自己創建一個類,繼承IDispose接口,讓它可以用在USING語句中。這里我們應該區分一下析構方法,與dispose方法。我們知道析構方法一定會執行,但是不知道什么時候執行。我們

知道dispose方法什么時候執行,但是不知道它會不會執行,因為類里有dispose方法,不代表一定會把這個類用在using語句中。此時,我們就可以通過析構方法來調用dispose方法,這樣可

以保證dispose方法一定被調用。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 余庆县| 丽水市| 灵川县| 额敏县| 丹东市| 浠水县| 钟山县| 泽库县| 凌海市| 恭城| 杨浦区| 东莞市| 长沙县| 香港 | 泰和县| 洛阳市| 诸暨市| 葵青区| 兴文县| 金坛市| 麻阳| 博爱县| 南郑县| 锡林浩特市| 咸阳市| 新民市| 上杭县| 公安县| 浪卡子县| 屏东县| 永平县| 宣恩县| 津南区| 饶河县| 大田县| 文安县| 泰安市| 奈曼旗| 安庆市| 宾阳县| 双鸭山市|