2012-01-02 30 views
1

我用BlockingCollection爲我的實驗實施了生產者/消費者模式。運行後GC爲什麼不收集未使用的對象?

PerformanceCounter c = null; 
void Main() 
{ 
    var p =System.Diagnostics.Process.GetCurrentProcess(); 
    c = new PerformanceCounter("Process", "Working Set - Private", p.ProcessName); 

    (c.RawValue/1024).Dump("start"); 
    var blocking = new BlockingCollection<Hede>(); 
    var t = Task.Factory.StartNew(()=>{ 
     for (int i = 0; i < 10000; i++) 
     { 
      blocking.Add(new Hede{ 
      Field = string.Join("",Enumerable.Range(0,100).Select (e => Path.GetRandomFileName())) 
      }); 
     } 
     blocking.CompleteAdding(); 
    }); 

    var t2 = Task.Factory.StartNew(()=>{ 
     int x=0; 
     foreach (var element in blocking.GetConsumingEnumerable()) 
     { 
      if(x % 1000==0) 
      { 
       (c.RawValue/1024).Dump("now"); 
      } 
      x+=1; 
     } 
    }); 
    t.Wait(); 
    t2.Wait(); 
    (c.RawValue/1024).Dump("end"); 
} 

我的內存轉儲:

start 
211908 
now 
211972 
now 
212208 
now 
212280 
now 
212596 
now 
212736 
now 
212712 
now 
212856 
now 
212840 
now 
212976 
now 
213036 
end 
213172 

我的內存是211908kb消費之前,但它同時從其他線程生產逐一增加。

GC沒有從內存中收集生成的對象。爲什麼我的記憶增量雖然實施了生產者/消費者模式

+0

我沒有看到任何Dispose或Using calls。我看到你將項目添加到集合中,並且從不刪除它們。我不太明白這個問題是什麼或你想達到什麼目的。 – Origin 2012-01-02 15:34:49

+1

我真的不明白你期望發生什麼? – Tudor 2012-01-02 15:34:51

+1

產地:它是生產者/消費者模式,我不需要從列表中刪除項目。 GetConsumingEnumerable()爲我移除項目 – oguzh4n 2012-01-02 15:40:10

回答

6

ConcurrentQueue<T>默認情況下使用BlockingCollection<T>contains a memory leak in .Net 4.0。我不確定這是你正在觀察的問題,但它可能是。

它應該在即將推出的.Net 4.5中修復。

+0

它看起來像內存泄漏。謝謝你的回答 – oguzh4n 2012-01-02 15:53:48

+0

儘管ConcurrentQueue是真的,但'泄漏'永遠不會超過隊列中未使用的部分。你通常會使用一個上限,比如'new BlockingCollection (100)',然後你可以永遠運行它。 – 2012-01-02 16:02:51

+0

@亨克,是的,與問題中的代碼一樣,隊列沒有任何限制,它很可能會首先被完全填充,然後纔會被消耗。如果是這種情況,那麼所有的物品都會泄漏。 – svick 2012-01-02 16:11:06

0

垃圾收集器不會自動釋放內存。處理未使用的對象後,您可以通過調用GC.Collect();強制垃圾回收。

+0

我試過'GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect ();'在't2.Wait();'行後面,沒關係 – oguzh4n 2012-01-02 15:43:40

相關問題