Parallel.ForEach () vs. foreach (IEnumerable <T> .AsParallel ())

143

Erg, estoy tratando de encontrar estos dos métodos en el BCL usando Reflector, pero no puedo localizarlos. ¿Cuál es la diferencia entre estos dos fragmentos?

UNA:

IEnumerable<string> items = ...

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

SI:

IEnumerable<string> items = ...

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

¿Existen diferentes consecuencias de usar uno sobre el otro? (Suponga que lo que sea que esté haciendo en los cuerpos entre corchetes de ambos ejemplos es seguro para subprocesos).

SnickersAreMyFave
fuente

Respuestas:

148

Hacen algo bastante diferente.

El primero toma el delegado anónimo y ejecuta múltiples hilos en este código en paralelo para todos los elementos diferentes.

El segundo no es muy útil en este escenario. En pocas palabras, tiene la intención de hacer una consulta en varios subprocesos, y combinar el resultado, y entregarlo nuevamente al subproceso de llamada. Por lo tanto, el código en la instrucción foreach permanece siempre en el hilo de la interfaz de usuario.

Solo tiene sentido si hace algo costoso en la consulta de linq a la derecha de la AsParallel()llamada, como:

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
svick
fuente
¿Cuál es el beneficio sobre simplemente hacer un foreach paralelo en el computafibonacci?
l --''''''--------- '' '' '' '' '' ''
51

La diferencia es que B no es paralelo. Lo único que AsParallel()hace es que se ajusta alrededor de a IEnumerable, de modo que cuando usa métodos LINQ, se usan sus variantes paralelas. El envoltorio GetEnumerator()(que se usa detrás de escena en el foreach) incluso devuelve el resultado de la colección original GetEnumerator().

Por cierto, si desea ver los métodos en Reflector, AsParallel()está en la System.Linq.ParallelEnumerableclase en el System.Coreensamblado. Parallel.ForEach()está en el mscorlibensamblado (espacio de nombres System.Threading.Tasks).

svick
fuente
¿Qué quiere decir con ... Sus variantes paralelas se utilizan ...?
l --''''''--------- '' '' '' '' '' ''
2
@punctuation Eso, por ejemplo, cuando escribes .Select(), llama ParallelEnumerable.Select()y no lo normal Enumerable.Select().
svick
50

El segundo método no será paralelo, la forma correcta de usar AsParallel () en su ejemplo sería

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});
Scott Chamberlain
fuente
3
¿Por qué usar la combinación de asparallel junto con forall en lugar de simplemente foreach?
l --''''''--------- '' '' '' '' '' ''