Erg, j'essaie de trouver ces deux méthodes dans la BCL à l'aide de 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 différentes conséquences d'utiliser l'un sur l'autre? (Supposons que tout ce que je fais dans les corps entre crochets des deux exemples est thread-safe.)
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 n'est pas très utile dans ce scénario. En résumé, il est prévu d'effectuer une requête sur plusieurs threads, de combiner le résultat et de le renvoyer au thread appelant. Le code de l'instruction foreach reste donc toujours sur le thread d'interface utilisateur.
Cela n’a de sens que si vous faites quelque chose de coûteux dans la requête linq à droite de l’appel AsParallel()
, comme:
var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
La différence est que B n'est pas parallèle. La seule chose que fait AsParallel()
, c'est qu'elle entoure un IEnumerable
, de sorte que lorsque vous utilisez des méthodes LINQ, leurs variantes parallèles sont utilisées. Le GetEnumerator()
du wrapper (qui est utilisé dans les coulisses du foreach
) renvoie même le résultat du GetEnumerator()
de la collection d'origine.
En passant, si vous souhaitez consulter les méthodes de Reflector, AsParallel()
est dans la classe System.Linq.ParallelEnumerable
De l’assemblage System.Core
. Parallel.ForEach()
est dans le mscorlib
assembleur (espace de nom System.Threading.Tasks
).
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
});