Цикл Parallel.ForEach с BlockingCollection.GetConsumableEnumerable

Почему цикл Parallel.ForEach завершается с OperationCancelledException при использовании GetConsumableEnumerable?

//outside the function
static BlockingCollection<double> _collection = new BlockingCollection<double>();
    
    
var t = Task.Factory.StartNew(Producer);            
Parallel.ForEach(_collection.GetConsumingEnumerable(),
    item => Console.WriteLine("Processed {0}", item));
Console.WriteLine("FINISHED processing");


public static void Producer()
{
     var data = Enumerable.Range(1, 1000);
     foreach (var i in data)
     {
        _collection.Add(i);
        Console.WriteLine("Added {0}",i);
     }
                    
     Console.WriteLine("Finished adding");
     _collection.CompleteAdding();
}



Ответы (1)


Как я недавно узнал, использование Parallel.ForEach с BlockingCollection несколько проблематично. Его можно заставить работать, но для этого потребуются дополнительные усилия.

У Стивена Туба есть отличная запись в блоге, и если вы загрузите проект Дополнения к параллельным расширениям (также доступен в NuGet) вы найдете готовый код, который вам поможет.

person Jon Skeet    schedule 07.07.2011
comment
Что меня действительно озадачивает, так это то, почему Parallel.ForEach выдает исключение, когда я вызываю _collection.CompleteAdding(). - person Sam; 07.07.2011
comment
@Sam: Честно говоря, я бы не хотел говорить. Там слишком много глубокой магии, чтобы я мог быть уверен в том, что говорю правильные вещи :) - person Jon Skeet; 07.07.2011
comment
Текущий URL-адрес Parallel Extensions Extras: code.msdn.microsoft.com/ParExtSamples и кто-то создал NuGet для расширений: nuget.org/packages/MSFT.ParallelExtensionsExtras - person Reyhn; 03.08.2016
comment
Более свежая статья Джана Билгина об этой комбинации — ссылка - person MuKa; 16.05.2018
comment
ссылка на блог: ParallelExtensionsExtras Tour — #4 — BlockingCollectionExtensions - person JonasH; 03.03.2021