Comment utiliser les attendent dans une boucle
Je suis en train de créer un asynchrones application console qui fait un peu de travail sur une collection. J'ai une version qui utilise la boucle for parallèle une autre version qui utilise async/await. Je m'attendais à la async/await version de travail similaire à la version parallèle, mais il s'exécute en mode synchrone. Ce que je fais mal?
class Program
{
static void Main(string[] args)
{
var worker = new Worker();
worker.ParallelInit();
var t = worker.Init();
t.Wait();
Console.ReadKey();
}
}
public class Worker
{
public async Task<bool> Init()
{
var series = Enumerable.Range(1, 5).ToList();
foreach (var i in series)
{
Console.WriteLine("Starting Process {0}", i);
var result = await DoWorkAsync(i);
if (result)
{
Console.WriteLine("Ending Process {0}", i);
}
}
return true;
}
public async Task<bool> DoWorkAsync(int i)
{
Console.WriteLine("working..{0}", i);
await Task.Delay(1000);
return true;
}
public bool ParallelInit()
{
var series = Enumerable.Range(1, 5).ToList();
Parallel.ForEach(series, i =>
{
Console.WriteLine("Starting Process {0}", i);
DoWorkAsync(i);
Console.WriteLine("Ending Process {0}", i);
});
return true;
}
}
Vous devez vous connecter pour publier un commentaire.
La façon dont vous utilisez le
await
mot-clé indique C# que vous voulez attendre à chaque fois que vous passer à travers la boucle, ce qui n'est pas parallèle. Vous pouvez réécrire votre méthode de ce genre pour faire ce que vous voulez, en stockant une liste deTask
s et puisawait
ing avecTâche.WhenAll
.Ending Process
notification n'est pas lorsque la tâche est en fait la fin. Toutes ces notifications sont sous-évaluées de façon séquentielle à droite après le dernier des tâches de finitions. Par le temps de vous voir "la Fin de Processus 1", 1 pourrait avoir été pendant une longue période de temps. Autres que le choix des mots, il y a, +1.Semaphore
dansDoWorkAsync
à la durée maximale de l'exécution des tâches?Votre code attend pour chaque opération (à l'aide de
await
) pour finir avant de commencer la prochaine itération.Par conséquent, vous n'obtenez pas de parallélisme.
Si vous souhaitez exécuter un existant opération asynchrone en parallèle, vous n'avez pas besoin
await
; vous avez juste besoin d'obtenir une collection deTask
s et appelTask.WhenAll()
pour retourner une tâche qui attend tous:await
fait exactement le contraire de ce que vous voulez – attend pour laTask
à la fin.DoWorkAsync
sur chaque élémentlist
(en passant de chaque élément dansDoWorkAsync
, ce qui je suppose a un seul paramètre)?Parfois, tous nous avons besoin est un copier + coller solution prête à l'emploi, donc, c'est l'ensemble de la solution de Tim.S.:
Et le résultat dans la console: