2011-07-07 26 views
17

¿Por qué parallel.ForEach loop sale con OperationCancelledException, mientras usa GetConsumableEnumerable?Parallel.ForEach loop con BlockingCollection.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(); 
} 

Respuesta

17

Usando Parallel.ForEach con BlockingCollection es algo problemático, como descubrí recientemente. Se puede hacer que funcione, pero necesita un pequeño esfuerzo adicional.

Stephen Toub tiene un excellent blog post on it, y si descarga el proyecto "Parallel Extension Extras" (also available on NuGet), encontrará algún código listo para ayudarlo.

+0

Lo que realmente me desconcierta es por qué Parallel.ForEach lanza una excepción cuando llamo _collection.CompleteAdding(). – Sam

+0

@Sam: no me gustaría decir, para ser sincero. Hay demasiada magia profunda allí para que tenga confianza en decir lo correcto :) –

+0

La URL actual para los Extras de Extensiones Paralelas: https://code.msdn.microsoft.com/ParExtSamples y alguien ha hecho un NuGet de las extensiones: https://www.nuget.org/packages/MSFT.ParallelExtensionsExtras/ – Reyhn