L'exécution des tâches en parallèle
Ok, donc en gros j'ai un tas de tâches (10) et je veux commencer en même temps et attendre pour eux de complet. Lorsque terminé, je veux exécuter d'autres tâches. J'ai lu un tas de ressources à ce sujet, mais je ne peux pas le faire juste pour mon cas particulier...
Voici ce que j'ai actuellement (code a été simplifié):
public async Task RunTasks()
{
var tasks = new List<Task>
{
new Task(async () => await DoWork()),
//and so on with the other 9 similar tasks
}
Parallel.ForEach(tasks, task =>
{
task.Start();
});
Task.WhenAll(tasks).ContinueWith(done =>
{
//Run the other tasks
});
}
//This function perform some I/O operations
public async Task DoWork()
{
var results = await GetDataFromDatabaseAsync();
foreach (var result in results)
{
await ReadFromNetwork(result.Url);
}
}
Donc mon problème est que lorsque je suis en attente de l'achèvement des tâches avec le WhenAll
appel, il me dit que toutes les tâches sont plus de même si aucun d'entre eux sont terminés. J'ai essayé d'ajouter Console.WriteLine
dans mon foreach
et quand je suis entré dans la poursuite de la tâche, des données de conserve de venir dans mon précédent Task
s qui ne sont pas vraiment fini.
Ce que je fais mal?
Task<Task>
quelque part (l'appel de la Tâche constructeur directement est un peu suspect) et vous voulez vraiment vous attendent à l'intérieur de la tâche. Pouvez-vous utiliser Task.Run
au lieu de la Tâche constructeur/Commencer? Task.Run
va faire le déballage pour vous.Donc vous pensez que je devrais faire: var tâches = new List<Tâche> { Tâche.Exécuter(()=> DoWork()) }
OriginalL'auteur Yann Thibodeau | 2015-12-19
Vous devez vous connecter pour publier un commentaire.
Vous devriez presque jamais utiliser le
Task
constructeur directement. Dans votre cas, la tâche ne se déclenche la tâche réelle que vous ne pouvez pas attendre pour.Vous pouvez simplement appeler
DoWork
et de revenir à une tâche, de le stocker dans une liste et attendre que toutes les tâches à effectuer. Sens:Cependant, les méthodes asynchrones exécuter simultanément jusqu'à ce que les premiers attendent sur une tâche inachevée est atteint. Si vous vous inquiétez au sujet de cette partie de prendre trop de temps alors utiliser
Task.Run
à se décharger sur un autreThreadPool
fil et ensuite le stocker que tâche dans la liste:Task.WhenAll
? Merci!J'ai été plus se référant à la partie synchrone de
DoWork
et pas le code en l'appelant.comme vous l'avez dit, Cependant, de méthodes asynchrones exécuter simultanément jusqu'à ce que les premiers attendent sur une tâche inachevée est atteint. ---- Voici DONC puis-je utiliser "en attente de tâche.delay(5).ConfigureAwait(false); déclaration de première ligne dans mon DoWork() la méthode? pour revenir au sujet principal et démarrer le pool de threads Thread pour exécuter remianing code dans la méthode ? Veuillez informer.
vous n'avez pas besoin
Task.Delay
. Vous avezTask.Yield
exactement à cette fin. Mais comme je le vois à l'aide deTask.Run
est mieux dans ce cas parce que c'est plus explicite à propos de "tirer" une nouvelle tâche.OriginalL'auteur i3arnon
Essentiellement, vous êtes de mélange à deux incompatibles async paradigmes, c'est à dire
Parallel.ForEach()
etasync-await
.Pour ce que vous voulez, procédez de l'une ou de l'autre. E. g. vous pouvez simplement utiliser
Parallel.For[Each]()
et de la chute de l'asynchrone attendent tout à fait.Parallel.For[Each]()
ne reviendra que lorsque toutes les tâches parallèles sont complètes, et vous pouvez ensuite déplacer sur les autres tâches.Le code a certains autres problèmes:
vous de marquer la méthode async mais ne pas attendre (l'attendent que vous avez est dans la délégué, pas la méthode);
vous voudrez certainement
.ConfigureAwait(false)
sur votre attend, surtout si vous n'êtes pas en train de l'utiliser immédiatement les résultats dans un thread d'INTERFACE utilisateur.OriginalL'auteur sellotape
Si vous voulez exécuter la tâche en parallèle dans différents threads à l'aide de TPL, vous mai besoin de quelque chose comme ceci:
Ces approche de parallélisation de seulement une petite quantité de code: les files d'attente de la méthode pour le pool de threads et le retour de l'inachevé
Task
. Également pour une telle petite quantité de la tâche de la parallélisation peut prendre plus de temps que la simple exécution asynchrone. Cela pourrait avoir de sens que si vos tâches à faire un peu plus (synchrone) de travail avant leur premier attendent.Pour la plupart des cas, une meilleure façon de l'être:
À mon avis dans votre code:
Vous ne devriez pas envelopper votre code dans
Task
avant de passer àParallel.ForEach
.Vous pouvez simplement
await
Task.WhenAll
au lieu d'utiliserContinueWith
.OriginalL'auteur Andrey Tretyak
La
DoWork
méthode est une méthode d'I/O asynchrone de la méthode. Cela signifie que vous n'avez pas besoin de plusieurs threads pour exécuter plusieurs d'entre eux, comme la plupart du temps, la méthode asynchrone attendre pour les I/O pour valider. Un thread est assez pour le faire.Vous devriez presque ne jamais utiliser le
Tâche
constructeur pour créer une nouvelle tâche. Pour créer un asynchronous I/O de la tâche, il suffit d'appeler laasync
méthode. Pour créer une tâche qui sera exécutée sur un thread du pool, l'utilisationTask.Run
. Vous pouvez lire cet article pour une explication détaillée deTask.Run
et d'autres options de création de tâches.OriginalL'auteur Jakub Lortz
Aussi simplement ajouter un bloc try-catch autour de la Tâche.WhenAll
NB: Une instance de Système.AggregateException est levée qui agit comme un wrapper autour d'une ou plusieurs exceptions qui ont eu lieu. Ceci est important pour les méthodes de coordonner plusieurs tâches comme la Tâche.WaitAll() et de la Tâche.WaitAny() de sorte que le AggregateException est capable d'envelopper toutes les exceptions dans l'exécution des tâches qui ont eu lieu.
OriginalL'auteur NiTRiX-Reloaded