2010-03-31 53 views
3

我有一段這樣的代碼:GC如何在.NET中收集靜態成員中的資源?

Class Program 
{ 
    static StreamReader sr = null; 
    static int var=0; 
    static Program() 
    { 
     sr = new StreamReader("input.txt") 
    } 

    ~Program() 
    { 
     sr.Dispose(); 
    } 

    static void main(string args[]) 
    { 
     //do something with input here 
    } 
} 

這可能不是一個很好的做法,但我只是想用這個例子來問解構和GC是如何工作的。

我的問題是:Will〜Program()會在非確定的時間被調用,或者在這種情況下根本不會被調用。如果解構器不會被調用,那麼GC如何收集非託管資源和管理資源。

回答

1

它可能不會回收這些資源,直到AppDomain或進程卸載。

如果你永遠不會實例化一個對象,它將永遠不會被銷燬。這正是你想要的東西,可能就像一個單身人士。我相信有一種叫做「Phoenix Singleton」的味道,它可以讓Singleton得到清理,然後在需要時重建。你可以使用WeakReference來實現它到單例對象。

在任何情況下,對於運行一段有限時間的簡單程序,除非它成爲問題,否則我不會擔心它......當進程退出時資源將被清理。

1

您的情況還不太清楚,因爲如果不創建類的實例,則不會調用終結器。

但是,只調用dispose對對象本身的垃圾收集沒有任何影響,它只是告訴對象釋放任何資源(特別是句柄等)。因此,如果您希望GC收集實例,則需要將參考設置爲null,並且如果沒有其他實例的實時引用,它最終將被收集。

基本上每個靜態引用都可以看作是根引用,它被包含在GC檢查活動引用中。無法通過實時參考(直接或間接)達到的所有實例都是收集的候選對象。如果引用「變量」是靜態的或不是靜態的。

1

靜態引用將爲實例創建根目錄,直到它明確設置爲null或其程序集被卸載。如果這兩種情況都不發生,則靜態參考指向的實例將繼續使用,因此不會收集。如果它不符合垃圾收集條件,它的終結器也不會被調用。

btw GC只處理託管內存。它不處理非託管資源。爲此你需要IDiposable和/或終結器。

1

C#中沒有靜態終結器(析構函數)。因此,除非實際創建了Program的實例,否則將永遠不會將~Program()稱爲

當(如果)它被調用時,它只調用StreamReaderDispose()方法;因爲在調用終結器之後仍然保留對StreamReader的引用,所以在程序退出之前,實例將永遠不會被垃圾收集。