2016-08-17 21 views
0

我正在實施一個無限的任務,每隔一段時間通過.net控制檯應用程序運行。不過,我擔心下面會導致內存泄漏。由於Main是靜態的(這是我關於垃圾收集的知識會變得模糊的地方)並不意味着我在try和catch中創建的對象不會被垃圾收集器拾取,直到Main完成(永遠不會)?從主要方法(無限循環)垃圾回收

有人能解釋一下垃圾收集器在這種情況下的行爲嗎?

public static void Main(string[] args) 
    { 
     Log.Logger = new LoggerConfiguration() 
     .MinimumLevel.Debug() 
     .WriteTo.RollingFile("Logs/log-{Date}.txt") 
     .CreateLogger(); 
     while (true) 
     { 
      try 
      { 
       Thread.Sleep(1000); 
       new UpdatePlayer().Run(); 
      } 
      catch (Exception ex) 
      { 
       Log.Error(ex.ToString()); 
      } 
     } 
    } 

回答

1

你有沒有內存泄漏:Main任何參考UpdatePlayer()例如:

... 
try 
{ 
    Thread.Sleep(1000); 

    // Instance created, executed 
    new UpdatePlayer().Run(); 
} 

// And can be safely collected here when the instance is out of scope (`try {...}`) 
// the anonymous instance can't be accessed and that's enough 

樣本內存泄漏:

// please notice, that anchor is outside the `while(true)` scope 
List<Object> anchor = new List<Object>(); 
... 

while (true) 
{ 
     try 
     { 
     Thread.Sleep(1000); 

     // Instance created 
     var item = new UpdatePlayer(); 
     // anchored 
     anchor.Add(item); 
     // and executed 
     item.Run();   
     } 

     // item can't be collected here: anchor has a reference to it 
     // And the item potentially can be accessed by, say, anchor[0] 

編輯:如果您將集合移動到while(true)範圍,代碼會沒有內存泄漏:

 try 
     { 
     List<object> pseudoAnchor = new List<object>(); 

     // Instance created 
     var item = new UpdatePlayer(); 
     // tried to be anchored (illusion) 
     pseudoAnchor.Add(item); 
     // and executed 
     item.Run();   
     } 
     ... 

     // the only reference to item is pseudoAnchor, but 
     // pseudoAnchor has not been referenced, and so GC 
     // can safely collect entire pseudoAnchor with all its items 
     // (just one `item` in fact) 
+0

這是一個非常好的例子。那麼收集一旦退出try塊就會發生嗎? – DeanR

+1

@DeanR:如果您將集合移動到'try'範圍內:'嘗試{列表 anchor = new List (); ...}這段代碼會再次沒有內存泄露:現在GC可以收集*整個集合*。 –

2

由於主要是靜態的(這是我的垃圾回收知識變得霧濛濛的),難道不是說,我的try和catch中創建對象將不會被垃圾收集器有所回升直到主要完成(這是從來沒有)?

不,這是錯誤的。

垃圾收集器能夠釋放任何可證明無法再從託管代碼訪問的對象的內存。在這種情況下,很明顯,Run方法結束後(除非在其他地方存儲對該對象的引用),則該對象將不再可訪問,因此GC可以釋放它(這可能需要一些時間才能完成) ,但它的允許)。

+0

在哪一步GC決定釋放呢?當它完成嘗試? – DeanR

+1

@DeanR每當它想要的地獄,或永遠不會。從字面上看,在任何時候它不能再被訪問和在時間結束之前。 – Servy