Possible Duplicate:
Possible memoryleak in ConcurrentBag?




我的应用程序中出现了史诗般的内存泄漏。我从未用一种方法添加到本地并发包集合中的所有数据。

这个简单的代码演示了如何使用它:

void Main()
{
    var l = new List<int>(){1,2,3,4};
    Func(l);
    l.Clear();
    l=null;
}

void Func(List<int> list)
{
    var bag = new ConcurrentBag<int>();
    Parallel.ForEach(list, k=> bag.Add(++k));

    list.Clear();

    foreach(int i in bag) //I know, I doing it wrong.
    {
        list.Add(i);
    }
}


我的期望:将创建bag并将其放在方法“ Func”处。

我看到的是:袋子永远不会被丢弃,保留在Parallel.ForEach中创建的所有线程,保留我添加到其中的所有数据。 =(

好的,当我将其添加到列表中时,可以使用“ TryTake”将其从包中删除。但是空袋仍然保留在记忆中。

现在,我通过使用List而不是ConcurrentBag解决问题。但是自从我的记忆丰富的人看到了这一点后,我睡不好觉。对不起,我的英语=)

更新

我更改了方法“ Func”:

void Func(List<int> list)
{
    var bag = new ConcurrentBag<int>();
    Parallel.ForEach(list, k=> bag.Add(++k));

    list.Clear();

    int i;
    while(bag.TryTake(out i))
    {
        list.Add(i);
    }

    bag = null;
    GC.Collect();
    GC.WaitForPendingFinalizers();
}


然后,我在VS中创建项目,编译并运行我的程序。此实例图是由“ .Net Memory Profiler 4.0”从内存快照创建的,我在程序完成所有工作后的10分钟内收集了该快照:

http://xmages.net/storage/10/1/0/f/d/upload/4c67f305.jpg
(抱歉,无法发布图片)

最佳答案

这是因为并发包将项目添加到线程的本地存储中。从线程的本地存储到包的引用是一个很强的引用,只要包中仍然有1个项目,就可以确保至少有1个线程引用该包并且不会将其收集。消耗掉袋子中的所有物品或使用其他容器。

请参阅:Possible memoryleak in ConcurrentBag?

10-05 17:42