225 votes

Parallel.ForEach vs Task.Run et Task.WhenAll

Quelles sont les différences entre l'utilisation de Parallel.ForEach ou de Task.Run () pour démarrer un ensemble de tâches de manière asynchrone?

Version 1:

 List<string> strings = new List<string> { "s1", "s2", "s3" };
Parallel.ForEach(strings, s =>
{
    DoSomething(s);
});
 

Version 2:

 List<string> strings = new List<string> { "s1", "s2", "s3" };
List<Task> Tasks = new List<Task>();
foreach (var s in strings)
{
    Tasks.Add(Task.Run(() => DoSomething(s)));
}
await Task.WhenAll(Tasks);
 

231voto

Reed Copsey Points 315315

Dans ce cas, la deuxième méthode asynchrone attendre pour les tâches à accomplir au lieu de la bloquer.

Cependant, il existe un inconvénient à l'utilisation Task.Run dans une boucle - Avec Parallel.ForEach, il y a un Partitioner qui va être créé pour éviter de faire plus de tâches que nécessaire. Task.Run , ce sera toujours une tâche unique par article (puisque vous êtes en train de faire), mais l' Parallel classe lots de travail de sorte que vous créez moins de tâches que l'ensemble des éléments de travail. Cela peut fournir une meilleure performance globale, surtout si le corps de la boucle a une petite quantité de travail par poste.

Si c'est le cas, vous pouvez combiner les deux options en écrivant:

await Task.Run(() => Parallel.ForEach(strings, s =>
{
    DoSomething(s);
}));

Notez que cela peut aussi être écrit dans ce court formulaire:

await Task.Run(() => Parallel.ForEach(strings, DoSomething));

51voto

SLaks Points 391154

La première version bloquera le thread appelant de manière synchrone (et exécutera certaines des tâches sur celui-ci).
S'il s'agit d'un thread d'interface utilisateur, cela gèlera l'interface utilisateur.

La deuxième version exécutera les tâches de manière asynchrone dans le pool de threads et libérera le thread appelant jusqu'à ce qu'ils aient terminé.

Il existe également des différences dans les algorithmes de planification utilisés.

Notez que votre deuxième exemple peut être raccourci à

 await Task.WhenAll(strings.Select(s => Task.Run(() => DoSomething(s)));
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X