Opérations asynchrones parallèles avec Parallel.ForEach
en C #
Améliorer les performances des applications implique souvent un traitement parallèle. Cependant, la combinaison d'opérations asynchrones (async
/ await
) avec des boucles parallèles comme Parallel.ForEach
présente des défis uniques. Cet article relève ces défis et fournit des solutions pour attendre correctement les tâches asynchrones dans une boucle parallèle.
Le problème: tâches asynchrones et Parallel.ForEach
Le mot-clé async
dans C # permet la programmation asynchrone, renvoyant un objet Task
. Le problème se pose lors de l'utilisation de méthodes async
dans Parallel.ForEach
parce que les fils d'arrière-plan n'attendent pas intrinsèquement les tâches asynchrones à terminer avant la fin de la boucle.
Considérez cet exemple:
<code class="language-csharp">var bag = new ConcurrentBag<object>(); Parallel.ForEach(myCollection, async item => { // Pre-processing var response = await GetData(item); bag.Add(response); // Post-processing }); var count = bag.Count; // count is often 0!</code>
count
Renvoie fréquemment 0 car le thread principal se déroule avant que les fils d'arrière-plan terminent leurs opérations asynchrones.
Solution: en utilisant Select
et Task.WhenAll
Une solution robuste implique Select
pour créer une collection d'objets Task
et Task.WhenAll
pour attendre que toutes les tâches se terminent:
<code class="language-csharp">var bag = new ConcurrentBag<object>(); var tasks = myCollection.Select(async item => { // Pre-processing var response = await GetData(item); bag.Add(response); // Post-processing }); await Task.WhenAll(tasks); var count = bag.Count; // count will be correct</code>
Cette approche initie les opérations asynchrones en utilisant simultanément Select
puis utilise Task.WhenAll
pour garantir que toutes les tâches se terminent avant d'accéder au bag
.
Solutions avancées: ForEachAsync
Pour des scénarios plus complexes, le billet de blog de Stephen Toub sur ForEachAsync
fournit une solution plus sophistiquée et adaptable:
https://www.php.cn/link/33edf41c0becd0d57c35c4e27276617b
Cela offre une méthode plus contrôlée et plus efficace pour gérer les opérations asynchrones parallèles, en particulier lorsque vous traitez des exceptions potentielles ou de l'annulation. Il fournit une approche plus robuste et flexible par rapport à la méthode simple Select
/ Task.WhenAll
.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!