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

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

編寫高質量代碼改善C#程序的157個建議——建議52:及時釋放資源

2019-11-14 14:05:43
字體:
來源:轉載
供稿:網友

建議52:及時釋放資源

垃圾回收機制自動為我們隱式地回收了資源(垃圾回收器會自動調用終結器),那我們為什么要主動釋放資源呢?

PRivate void buttonOpen_Click(object sender,EventArgs e){   FileStream fileStream = new FileStream(@"c:/test.txt",FileMode.Open);           }private void buttonGC_Click(object sender,EventArgs e){   System.GC.Collect();   }

這是一個WinForm窗體程序的例子,在這個示例中,單擊一個按鈕負責打開一個文件,單擊另一個按鈕負責回收說有“代”(代的概念會在下文詳細指出)的垃圾。如果連續兩次單擊打開文件的按鈕,系統就會報錯:

IOException:文件“c:/test.txt”正由另外一進程使用,因此該進程無法訪問此文件。

如果先單擊打開文件的按鈕,繼而再單擊清理按鈕,則運行正常。

 

現在來分析:在打開文件的方法中,方法執行完畢后,由于局部變量fileStream在程序中已經沒有任何地方引用了,所以它會在下一次垃圾回收時被運行時標記為垃圾。那么,什么時候會進行下一次垃圾回收呢,后者說垃圾回收器什么時候才開始真正進行回收工作呢?微軟官方的解釋是,當滿足以下條件之一時將發生垃圾回收:

  • 系統具有低的物理內存。
  • 由托管堆上已分配的對象使用的內存超出了可接受的閾值。 這意味著可接受的內存使用的閾值已超過托管堆。 隨著進程的運行,此閾值會不斷地進行調整。
  • 調用 GC.Collect 方法。 幾乎在所有情況下,您都不必調用此方法,因為垃圾回收器會持續運行。 此方法主要用于特殊情況和測試。

 

不及時釋放資源是對系統的一種極大的浪費,這種浪費還會干擾程序的正常運行(如在本實例中,由于它始終占著文件資源,導致我們不能再次使用這個文件資源了)。

若果類型本身繼承了IDisposable接口,垃圾回收機制雖然會自動幫我們釋放資源,但是這個過程卻延長了,因為它不是在一次回收中完成所有的清理工作。本例中因為fileStream繼承了IDisposable接口,故第一次進行垃圾回收時,垃圾回收器會調用fileStream的終結器,然后等待下一次的垃圾回收,這時fileStream對象才有可能被真正的回收掉。

我們來改進這個程序:

private void buttonOpen_Click(object sender,EventArgs e){    FileStream fileStream = new FileStream(@"c:/test.txt",FileMode.Open);         fileStream.Dispose();      }

但是如果第一行代碼出現異常,就永遠執行不了filsStream.Dispose()了。再次改進:

private void buttonOpen_Click(object sender,EventArgs e){    try    {           FileStream fileStream = new FileStream(@"c:/test.txt",FileMode.Open);         }    finally    {        fileStream.Dispose();          }}

使用語法糖“using"關鍵字進一步簡化:

private void buttonOpen_Click(object sender,EventArgs e){    using(FileStream fileStream = new FileStream(@"c:/test.txt",FileMode.Open))    {        }}

 

 

關于“代數”:一共分為3代:第0代、第1代、第2代。

  • 第 0 代:這是最年輕的代,其中包含短生存期對象。 短生存期對象的一個示例是臨時變量。 垃圾回收最常發生在此代中。新分配的對象構成新一代的對象并且為隱式的第 0 代回收,除非它們是大對象,在這種情況下,它們將進入第 2 代回收中的大對象堆。大多數對象通過第 0 代中的垃圾回收進行回收,不會保留到下一代。
  • 第 1 代:這一代包含短生存期對象并用作短生存期對象和長生存期對象之間的緩沖區。
  • 第 2 代:這一代包含長生存期對象。 長生存期對象的一個示例是服務器應用程序中的一個包含在進程期間處于活動狀態的靜態數據的對象。

當條件得到滿足時,垃圾回收將在特定代上發生。 回收某個代意味著回收此代中的對象及其所有更年輕的代。 第 2 代垃圾回收也稱為完整垃圾回收,因為它回收所有代上的所有對象(即,托管堆中的所有對象)。

幸存和提升

垃圾回收中未回收的對象也稱為幸存者,并會被提升到下一代。 在第 0 代垃圾回收中幸存的對象將被提升到第 1 代;在第 1 代垃圾回收中幸存的對象將被提升到第 2 代;而在第 2 代垃圾回收中幸存的對象將仍為第 2 代。

當垃圾回收器檢測到某個代中的幸存率很高時,它會增加該代的分配閾值,因此下一次回收將會獲取一個非常大的回收內存。 CLR 會在以下兩個優先級別之前進行平衡:不允許應用程序的工作集獲取太大內存以及不允許垃圾回收花費太多時間。

暫時代和暫時段

因為第 0 代和第 1 代中的對象的生存期較短,因此,這些代被稱為暫時代。

暫時代必須在稱為暫時段的內存段中進行分配。 垃圾回收器獲取的每個新段將成為新的暫時段,并包含在第 0 代垃圾回收中幸存的對象。 舊的暫時段將成為新的第 2 代段。

 

更多內容可參考MSDN:垃圾回收的基礎

 

 

轉自:《編寫高質量代碼改善C#程序的157個建議》陸敏技


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 泾川县| 黄龙县| 安仁县| 泰安市| 宁城县| 昌图县| 兴业县| 射洪县| 阳城县| 攀枝花市| 寿宁县| 兴山县| 公主岭市| 无锡市| 伽师县| 弋阳县| 涿州市| 江陵县| 大余县| 沙雅县| 老河口市| 自贡市| 特克斯县| 临泉县| 巩义市| 犍为县| 凤台县| 浮梁县| 新源县| 湄潭县| 遵化市| 张家界市| 信宜市| 焦作市| 思茅市| 专栏| 泰兴市| 天等县| 渝中区| 杭州市| 高台县|