相关疑难解决方法(0)

Parallel.ForEach Misbehavior

可能重复:
并行处理期间的C#值存储

我今天在我的控制台应用程序中运行了一些性能测试,我偶然发现了一些非常意外的事情.我的代码:

int iterations = 1000000;

var mainList = new List<string>();

for (int i = 0; i < iterations; i++)
{
    mainList.Add(i.ToString());
}

var listA = new List<string>();

Parallel.ForEach(mainList, (listItem) =>
                           {
                               if (Int32.Parse(listItem)%2 == 0)
                               {
                                   listA.Add(listItem);
                               }
                           });

Console.WriteLine("Parallel Count: {0}", listA.Count);

var listB = new List<string>();
foreach (var listItem in mainList)
{
    if (Int32.Parse(listItem) % 2 == 0)
    {
        listB.Add(listItem);
    }
}

Console.WriteLine("Sequential Count: {0}", listB.Count);
Run Code Online (Sandbox Code Playgroud)

这产生了一个输出:

平行计数:495939

顺序计数:500000

我运行了几次,并行循环似乎永远不会在适当的时间执行.任何人都能解释这种"不端行为"吗?并行循环是否值得信赖?

PS我知道在提供的代码示例中有很多废话,比如ToString()调用一个整数而不是解析它们但这只是我在测试时提出的随机代码.提前致谢.

c# parallel-processing task-parallel-library

11
推荐指数
1
解决办法
3907
查看次数

ConcurrentBag中可能的内存泄漏?

我一直在阅读新的并发集合,特别是ConcurrentBag引起了我的注意.由于ConcurrentBag在每个单独的线程上内部拥有一个本地集来使用它来跟踪项目,这意味着当线程本身超出范围时,ConcurrentBag仍将在内存中引用它.这反过来意味着线程声称的内存,以及本机资源?(请原谅我不知道.NET线程对象的确切内部工作原理)

我可以假设一个用例,你有一个全局ConcurrentBack用于多线程webservice,你有很多客户端添加任务.这些任务由线程池上的线程添加.现在,线程池是一种非常有效的管理线程的方法,但它确实根据工作量删除并创建了线程.因此,这样的web服务有时会发现自己遇到麻烦,因为底层包仍在引用许多应该被破坏的线程.

我创建了一个快速应用程序来测试此行为:

    static ConcurrentBag<int> bag = new ConcurrentBag<int>();
    static void FillBag() { for (int i = 0; i < 100; i++) { bag.Add(i); } }
    static void PrintState() { Console.WriteLine("Bag size is: {0}", bag.Count); }
    static void Main(string[] args)
    {
        var remote = new Thread(x =>
        {
            FillBag();
            PrintState();
        });
        // empty bag
        PrintState();
        // first 100 items are added on main thread
        FillBag();
        PrintState();
        // second 100 items are added on remote thread
        remote.Start();
        remote.Join();
        // since the …
Run Code Online (Sandbox Code Playgroud)

.net concurrency

8
推荐指数
1
解决办法
4183
查看次数

ConcurrentBag导致内存泄漏吗?

可能重复:
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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的期望:将创建包并在方法"Func"处置.

我所看到的:bag永远不会被释放,保存在Parallel.ForEach中创建的所有线程,保存我添加的所有数据.=(

好的,当我将它添加到列表中时,我可以使用"TryTake"从包中删除项目.但空袋仍然留在记忆中.

现在我通过使用List而不是ConcurrentBag来解决问题.但是因为我在记忆中看到这个,所以我睡不好觉.抱歉我的eng =)

UPDATE

我改变了我的方法"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();
}
Run Code Online (Sandbox Code Playgroud)

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

c# memory-leaks task-parallel-library concurrent-collections

3
推荐指数
1
解决办法
4729
查看次数