525 votes

Utiliser async / await pour plusieurs tâches

Je suis en utilisant une API client qui est complètement asynchrounous, qui est, chaque opération renvoie Task ou Task<T>, e.g:

static async Task DoSomething(int siteId, int postId, IBlogClient client)
{
    await client.DeletePost(siteId, postId); // call API client
    Console.WriteLine("Deleted post {0}.", siteId);
}

En utilisant le C# 5 async/await opérateurs, est-ce le bon/le moyen le plus efficace de commencer plusieurs tâches et d'attendre qu'elles se terminent:

int[] ids = new[] { 1, 2, 3, 4, 5 };
Parallel.ForEach(ids, i => DoSomething(1, i, blogClient).Wait());

ou:

int[] ids = new[] { 1, 2, 3, 4, 5 };
Task.WaitAll(ids.Select(i => DoSomething(1, i, blogClient)).ToArray());

Depuis l'API client est à l'aide de HttpClient en interne, je m'attendrais à ce à la question 5 requêtes HTTP immédiatement, écrit à la console que chacun complète.

714voto

tugberk Points 16203
int[] ids = new[] { 1, 2, 3, 4, 5 };
Parallel.ForEach(ids, i => DoSomething(1, i, blogClient).Wait());

Bien que vous exécutez les opérations en parallèle avec le code ci-dessus, ce code bloque chaque thread que chaque opération s'exécute sur l'. Par exemple, si le réseau d'appel prend 2 secondes, chaque thread se bloque pendant 2 secondes w/o fait rien, mais l'attente.

int[] ids = new[] { 1, 2, 3, 4, 5 };
Task.WaitAll(ids.Select(i => DoSomething(1, i, blogClient)).ToArray());

D'autre part, le code ci-dessus avec WaitAll également des blocs de threads et de votre fils de ne pas être libre de tout processus de d'autres travaux jusqu'à la fin des opérations. Je préfère WhenAll qui permettra d'effectuer vos opérations de manière asynchrone en Parallèle.

public async Task DoWork() {

    int[] ids = new[] { 1, 2, 3, 4, 5 };
    await Task.WhenAll(ids.Select(i => DoSomething(1, i, blogClient)));
}

Pour soutenir ceci, ici, vous trouverez un post de blog en passant par toutes les des alternatives et de leurs avantages/inconvénients: Comment et Où le cumul des e/S Asynchrones avec ASP.NET Web API

26voto

James Manning Points 7989

Puisque l'API que vous appelez est asynchrone, la version de Parallel.ForEach n'a pas beaucoup de sens. Vous ne devriez pas utiliser .Wait dans la version WaitAll car cela perdrait le parallélisme. Une autre alternative si l'appelant est async utilise Task.WhenAll après avoir fait Select et ToArray pour générer le tableau des tâches. Une deuxième alternative utilise Rx 2.0

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