3

可能重复:
ConcurrentBag 中可能存在内存泄漏?

我的应用程序中有史诗般的内存泄漏。我以一种方法添加到本地 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);
    }
}

我所期望的:将在“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 (抱歉,无法发布图片)

4

1 回答 1

9

这是因为并发包将项目添加到线程的本地存储中。线程本地存储对包的引用是强引用,只要包中还有1个项目,就保证至少有1个线程引用包,不会被收集。用完袋子里的所有物品或使用不同的容器。

请参阅:ConcurrentBag 中可能存在内存泄漏?

于 2012-02-13T07:18:07.350 回答