BlockingCollection with Parallel.For hangs?

本文关键字:hangs For Parallel with BlockingCollection | 更新日期: 2023-09-27 18:36:09

我正在玩BlockingCollection以尝试更好地理解它们,但是当我使用Parallel.For时,我正在努力理解为什么我的代码在完成处理我的所有项目时

挂起

我只是在上面添加一个数字(制片人?

var blockingCollection = new BlockingCollection<long>();
Task.Factory.StartNew(() =>
{
    while (count <= 10000)
    {
        blockingCollection.Add(count);
        count++;
    }
});

然后我正在尝试处理(消费者?

Parallel.For(0, 5, x => 
{
    foreach (long value in blockingCollection.GetConsumingEnumerable())
    {
        total[x] += 1;
        Console.WriteLine("Worker {0}: {1}", x, value);
    }
});

但是当它完成处理所有数字时,它就挂在那里了?我做错了什么?

另外,当我将 Parallel.For 设置为 5 时,是否意味着它正在处理 5 个独立线程上的数据?

BlockingCollection with Parallel.For hangs?

名思义,当BlockingCollection<T>块上无法执行任何操作时,这包括GetConsumingEnumerable()

这样做的原因是,该系列无法判断您的制作人是否已经完成,或者只是忙于制作下一个项目。

您需要做的是通过调用 CompleteAdding() 来通知集合您已完成向其添加项目。例如:

while (count <= 10000)
{
    blockingCollection.Add(count);
    count++;
}
blockingCollection.CompleteAdding();
这是一个

GetConsumingEnumerable方法功能。

如果没有任何项可用或集合为空,则以这种方式枚举集合会阻止使用者线程。

您可以在此处阅读更多相关信息

此外,使用 Parallel.For(0,5) 并不能保证数据将在 5 个单独的线程中处理。这取决于Environment.ProcessorCount.

另外,当我将 Parallel.For 设置为 5 时,是否意味着它正在处理 5 个独立线程上的数据?

不,引用SO中的先前答案(Parallel.For(Foreach)将创建多少个线程?默认最大并行度?

任务并行库和 PLINQ 的默认调度程序使用 .NET Framework ThreadPool 用于排队和执行工作。在 .NET 中 框架 4,线程池使用由 System.Threading.Tasks.Task 类型,以有效地支持 并行的细粒度并行性(短期工作单元) 任务和查询通常表示。

简而言之,TPL 创建任务,而不是线程。框架决定应该处理多少个线程。