在這里,對象可以通過兩種方式被清除。第一種方式是通過 IDisposable 接口的 Dispose 方法。此方法在對象顯式地結束時被客戶代碼調用,它調用 InternalD" name="description" />

深入.NET托管堆(managedheap)(下)

發表于:2007-05-25來源:作者:點擊數: 標簽:managedheap宋體.NET深入托管
MI LY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在這里,對象可以通過兩種方式被清除。第一種方式是通過 IDisposable 接口的 Dispose 方法。此方法在對象顯式地結束時被客戶代碼調用,它調用 InternalD

MILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">在這里,對象可以通過兩種方式被清除。第一種方式是通過IDisposable接口的Dispose方法。此方法在對象顯式地結束時被客戶代碼調用,它調用InternalDispose(true)。在這種情況下所有的對象都被清除了。如果析構函數被調用,那么InternalDispose(false)被調用,此時只有外部資源會被釋放。如果我們已經執行了終止操作,那么我們自己的對象有可能已經被釋放了,此后對它們的引用有可能引起異常。

 

GC.SuppressFinalize的調用會阻止垃圾收集器將對象放入終止隊列中。這樣做可以降低在一次GC過程中由于整理對象而引起的內存消耗,并且由于終止操作不會被調用,從而使性能得到提高。

 

C#的優化

 

因此使用IDisposable.Dispose()來釋放資源是個很好的方式,它不但可以減少一些在托管堆上進行操作的內存需求,而且能夠減少必須執行終止操作的對象的數量。但是它使用起來比較麻煩,尤其是有多個臨時對象被創建的時候更是如此。為了能夠從IDisposable接口受益,C#客戶程序應該書寫象下面這樣的代碼:

 

OverdueBookLocator bookLocator = null;

try

{

    bookLocator = new OverdueBookLocator();

    // Use bookLocator here

    Book book = bookLocator.Find("Eiffel, the Language");

    .

    .

    .

}

finally

{

    if(bookLocator != null)

    {

        IDisposable disp = bookLocator as IDisposable;

        disp.Dispose();

    }

}

 

finally中的代碼被用來在有異常發生時作適當的清理工作。為了C#客戶程序能夠簡單有效地使用Dispose模式,Beta2引入了using表達式。Using表達式允許你簡化你的代碼,因此上面的代碼可以寫成:

 

 

using(bookLocator = new OverdueBookLocator())

{

   // Use bookLocator here

   Book book = bookLocator.Find("Eiffel, the Language");

}

 

無論何時分配具有明確定義的生存期的類型時,你都應該使用using表達式。它能保證對IDisposable接口的適當調用,即使是在有異常發生的時候。

 

使用System.GC

 

System.GC類用來訪問被.NET framework暴露出來的垃圾回收機制。這個類包含以下一些有用的方法:

 

     GC.SuppressFinalize 這個方法在前面已經描述過了,它能夠抑制終止操作。如果你已經將屬于一個對象的外部資源釋放了,調用這個方法來抑制此對象的終止操作的執行。

     GC.Collect 具有兩個版本。不帶參數的版本在托管堆的所有generation上執行回收動作。另一個版本帶有一個整型參數,此參數指明所要進行回收操作的generation。你將很少調用這個方法,因為垃圾收集器在需要的時候會自動調用它。

     GC.GetGeneration 返回作為參數傳入的對象所在的generation。這個方法在由于性能的原因而進行的調試和跟蹤中很有作用,但是在大部分應用中作用有限。

     GC.GetTotalMemory 返回堆中已經被分配的內存總量。由于托管堆的工作方式,這個數字并不精確,但是如果你以true作為參數的話,還是會得到一個比較接近的近似值。這個方法在計算之前會先執行一遍回收操作。

 

下面是使用這些方法的一個例子:

 

/// <summary>

/// Displays current GC information

/// </summary>

/// <param name="generation">The generation to collect</param>

/// <param name="waitForGC">Run GC before calculating usage?</param>

public void CollectAndAudit(int generation, bool waitForGC)

{

  int myGeneration = GC.GetGeneration(this);

  long totalMemory = GC.GetTotalMemory(waitForGC);

  Console.WriteLine("I am in generation {0}.", myGeneration);

  Console.WriteLine("Memory before collection {0}.", totalMemory);

  GC.Collect(generation);

  Console.WriteLine("Memory after collection {0}.", totalMemory);

}

 

關于本文作者

 

Mickey WilliamsCodev Technologies的創始人之一。Codev Technologies是一家從事位Windows程序開發者提供咨詢和工具的機構。他同時也是.NET Experts (http://www.codeguru.com/columns/DotNet/www.dotnetexperts.com)的主要成員,他在此講授.NET Framework的課程。他時常在美國和歐洲的一些研討會上發表演講,并且已經寫了八本有關Windows程序設計方面的著作。他目前正被微軟出版社邀請寫作“Microsoft Visual C#”。你可以在mw@codevtech.com找到他。

原文轉自:http://www.anti-gravitydesign.com

評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97