C# 为什么GC不收集未使用的对象?

C# 为什么GC不收集未使用的对象?,c#,memory-management,producer-consumer,C#,Memory Management,Producer Consumer,我在实验中使用BlockingCollection实现了生产者/消费者模式 PerformanceCounter c = null; void Main() { var p =System.Diagnostics.Process.GetCurrentProcess(); c = new PerformanceCounter("Process", "Working Set - Private", p.ProcessName); (c.RawValue/1024).Dum

我在实验中使用BlockingCollection实现了生产者/消费者模式

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");
}
在消耗之前,我的内存是211908kb,但在从其他线程生成时,它一个接一个地增加


GC没有从内存中收集生成的对象。尽管实现了生产者/消费者模式,为什么我的内存会增加?

垃圾收集器不会一直自动释放内存。您可以通过调用
GC.Collect()强制垃圾收集在处理未使用的对象后。

垃圾收集器不会一直自动释放内存。您可以通过调用
GC.Collect()强制垃圾收集默认情况下由
BlockingCollection使用的
ConcurrentQueue
。我不确定这是你观察到的问题,但它可能是

它应该在即将推出的.Net 4.5中修复。

默认情况下由
BlockingCollection使用的
ConcurrentQueue
。我不确定这是你观察到的问题,但它可能是


它应该在即将发布的.Net 4.5中修复。

我没有看到任何Dispose或Using调用。我看到您将项目添加到集合中而从不删除它们。我不太明白问题是什么,也不太明白你们想达到什么目的。我真的不明白你们期望发生什么?来源:这是生产者/消费者模式,我不需要从列表中删除项目。GetConsumingEnumerable()为我删除项您的结果不表示泄漏或任何东西。许多项目消耗内存,而您的差异很小。运行2天,它可能会稳定下来。你的标题与你的问题不匹配!当GC决定收集未使用的对象时,它会收集未使用的对象。由于不存在GC.Collect调用,所以只要程序创建对象,您就可以进行测量。我看不到任何Dispose或Using调用。我看到您将项目添加到集合中而从不删除它们。我不太明白问题是什么,也不太明白你们想达到什么目的。我真的不明白你们期望发生什么?来源:这是生产者/消费者模式,我不需要从列表中删除项目。GetConsumingEnumerable()为我删除项您的结果不表示泄漏或任何东西。许多项目消耗内存,而您的差异很小。运行2天,它可能会稳定下来。你的标题与你的问题不匹配!当GC决定收集未使用的对象时,它会收集未使用的对象。由于没有GC.Collect调用,您只需在程序创建对象时进行测量;GC.WaitForPendingFinalizers();GC.Collect()
t2.Wait()之后行,不需要尝试
GC.Collect();GC.WaitForPendingFinalizers();GC.Collect()
t2.Wait()之后行,无所谓虽然ConcurrentQueue是真的,但“泄漏”永远不会超过队列中未使用的部分。你通常会使用一个上限,比如
new BlockingCollection(100)
,然后你就可以永远运行它了。@Henk,是的,但是有了问题中的代码,队列就没有边界了,很有可能它会首先被完全填充,然后才被消耗掉。如果是这样的话,那么所有的项目都会泄漏。虽然ConcurrentQueue是真的,但是“泄漏”永远不会超过队列中未使用的部分。你通常会使用一个上限,比如
new BlockingCollection(100)
,然后你就可以永远运行它了。@Henk,是的,但是有了问题中的代码,队列就没有边界了,很有可能它会首先被完全填充,然后才被消耗掉。如果是这样,那么所有的物品都会泄漏。
start
211908
now
211972
now
212208
now
212280
now
212596
now
212736
now
212712
now
212856
now
212840
now
212976
now
213036
end
213172