2013-04-08 35 views
0

我試圖弄清楚如何GC /終結者在C#工作,所以我寫了下面的程序。但是在ReadKey之後,終結器被稱爲36193次。我認爲它應該只在程序結束並且AppDomain卸載時調用一次。我在這裏錯過了什麼,這是如何工作的?終結器如何工作?

private class GCAnalyzer 
    { 
     private static int count = 0; 
     ~GCAnalyzer() 
     { 
      if (!AppDomain.CurrentDomain.IsFinalizingForUnload()) 
      { 
       count++; 
       GC.ReRegisterForFinalize(this); 
       Console.WriteLine("GC " + count); 
      } 
     } 
    } 

    static void Main(string[] a) 
    { 
     new GCAnalyzer(); 

     Console.ReadKey(); 
    } 
+0

你看過msdn文檔嗎? – 2013-04-08 12:44:01

+1

它看起來像你想垃圾收集器重新收集它。 – 2013-04-08 12:44:34

+4

你爲什麼要重新登錄? – Spook 2013-04-08 12:45:36

回答

2

如果我沒有理解錯的,那麼你在呼喚〜GCAnalyzer()當對象是「未鏈接」,而代碼時,你說這是不是準備將「無關聯」通過GC.ReRegisterForFinalize(此),這意味着在下次檢查時它還沒有被使用,並且它的結束代碼被運行...重新註冊自己......等等。

+0

我在想,當GC集合發生時,終結器會被調用,之後AppDomain將被卸載,因此對象將不會重新註冊自己。那麼會發生什麼呢?終結者線程在AppDomain卸載之前一直調用這個終結器? – Laurijssen 2013-04-08 13:03:07

0

關鍵是添加!Environment.HasShutdownStarted檢查。然後在每個集合上調用終結器並將其放回到最終列表中。所以在這個程序中,終結者被稱爲3次。每次GC.Collect兩次,然後將其註冊回到最終列表中,這是應用程序關閉時的第三次,然後不重新註冊,因此可以優雅地關閉dowb。

private class GCAnalyzer 
    { 
     private static int count = 0; 
     ~GCAnalyzer() 
     { 
      Console.WriteLine("GC " + count); 
      if (!AppDomain.CurrentDomain.IsFinalizingForUnload() &&!Environment.HasShutdownStarted) 
      { 
       count++; 
       GC.ReRegisterForFinalize(this);      
      } 
     } 
    } 

    static void Main(string[] a) 
    { 
     new GCAnalyzer(); 

     Console.ReadKey(); 

     GC.Collect(); 

     Console.ReadKey(); 

     GC.Collect(); 
    }