2010-09-24 13 views
126

Erg, sto cercando di trovare questi due metodi nel BCL utilizzando Reflector, ma non riesco a trovarli. Qual è la differenza tra questi due frammenti?Parallel.ForEach() rispetto a foreach (IEnumerable <T> .AsParallel())

A:

IEnumerable<string> items = ... 

Parallel.ForEach(items, item => { 
    ... 
}); 

B:

IEnumerable<string> items = ... 

foreach (var item in items.AsParallel()) 
{ 
    ... 
} 

ci sono diverse conseguenze derivanti dall'utilizzo di uno sopra l'altro? (Supponiamo che qualunque cosa stia facendo nei corpi tra parentesi di entrambi gli esempi sia thread-safe.)

risposta

138

Fanno qualcosa di diverso.

Il primo accetta il delegato anonimo ed esegue più thread su questo codice in parallelo per tutti i diversi elementi.

Il secondo non è molto utile in questo scenario. In breve, è inteso a fare una query su più thread e combinare il risultato e restituirlo al thread chiamante. Quindi il codice sull'istruzione foreach rimane sempre sul thread dell'interfaccia utente.

Ha senso solo se si fa qualcosa di costoso nella query LINQ alla destra della chiamata AsParallel(), come:

var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n)); 
+0

Qual è il vantaggio sopra semplicemente facendo un foreach parallelo sul computefibonacci? –

46

La differenza è, B non è parallelo. L'unica cosa che fa AsParallel() è che si estende attorno a uno IEnumerable, in modo che quando si usano i metodi LINQ, vengono utilizzate le loro varianti parallele. Il wrapper GetEnumerator() (che viene utilizzato dietro le quinte nel foreach) restituisce anche il risultato della collezione originale GetEnumerator().

BTW, se si desidera osservare i metodi in Reflector,è nella classe System.Linq.ParallelEnumerable nell'assemblaggio System.Core. Parallel.ForEach() è nell'assieme mscorlib (spazio nomi System.Threading.Tasks).

+0

Cosa intendi per ... Le loro varianti parallele sono usate ...? –

+1

@punctuation Che, ad esempio, quando scrivi '.Select()', chiama 'ParallelEnumerable.Select()' e non il normale 'Enumerable.Select()'. – svick

42

Il secondo metodo non sarà parallelo il modo corretto di utilizzare AsParallel() nel tuo esempio sarebbe

IEnumerable<string> items = ... 

items.AsParallel().ForAll(item => 
{ 
    //Do parallel stuff here 
}); 
+1

Perché utilizzare la combinazione di asparallel con forall invece di semplicemente foreach? –

Problemi correlati