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

143

Erg, j'essaie de trouver ces deux méthodes dans le BCL en utilisant Reflector, mais je ne peux pas les localiser. Quelle est la différence entre ces deux extraits?

UNE:

IEnumerable<string> items = ...

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

B:

IEnumerable<string> items = ...

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

Y a-t-il des conséquences différentes de l'utilisation de l'un par rapport à l'autre? (Supposons que tout ce que je fais dans les corps entre crochets des deux exemples est thread-safe.)

SnickersAreMyFave
la source

Réponses:

148

Ils font quelque chose de très différent.

Le premier prend le délégué anonyme et exécute plusieurs threads sur ce code en parallèle pour tous les différents éléments.

Le second pas très utile dans ce scénario. En un mot, il est prévu de faire une requête sur plusieurs threads, de combiner le résultat et de le redonner au thread appelant. Ainsi, le code de l'instruction foreach reste toujours sur le thread d'interface utilisateur.

Cela n'a de sens que si vous faites quelque chose de cher dans la requête linq à droite de l' AsParallel()appel, comme:

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
svick
la source
Quel est l'avantage de simplement faire un foreach parallèle sur le computefibonacci?
l --''''''--------- '' '' '' '' '' ''
51

La différence est que B n'est pas parallèle. La seule chose à AsParallel()faire est qu'il s'enroule autour de a IEnumerable, de sorte que lorsque vous utilisez des méthodes LINQ, leurs variantes parallèles sont utilisées. Le wrapper GetEnumerator()(qui est utilisé dans les coulisses du foreach) renvoie même le résultat de la collection d'origine GetEnumerator().

BTW, si vous souhaitez examiner les méthodes de Reflector, AsParallel()est dans la System.Linq.ParallelEnumerableclasse de l' System.Coreassembly. Parallel.ForEach()se trouve dans l' mscorlibassembly (espace de noms System.Threading.Tasks).

svick
la source
Qu'entendez-vous par ... Leurs variantes parallèles sont utilisées ...?
l --''''''--------- '' '' '' '' '' ''
2
@punctuation Que, par exemple, lorsque vous écrivez .Select(), il appelle ParallelEnumerable.Select()et non la normale Enumerable.Select().
svick
50

La deuxième méthode ne sera pas parallèle, la manière correcte d'utiliser AsParallel () dans votre exemple serait

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});
Scott Chamberlain
la source
3
Pourquoi utiliser la combinaison d'asparallel avec forall au lieu de simplement foreach?
l --'''''--------- '' '' '' '' '' ''