L'Utilisation De La Tâche.WaitAll() pour gérer attendu tâches?
Idéalement ce que je veux faire est de retarder une tâche avec un non-mode de blocage, puis attendez que toutes les tâches à effectuer. J'ai essayé d'ajouter la tâche de l'objet retourné par la Tâche.Retard et ensuite utiliser Tâche.WaitAll mais il semble que cela ne va pas aider. Comment dois-je résoudre ce problème?
class Program
{
public static async void Foo(int num)
{
Console.WriteLine("Thread {0} - Start {1}", Thread.CurrentThread.ManagedThreadId, num);
var newTask = Task.Delay(1000);
TaskList.Add(newTask);
await newTask;
Console.WriteLine("Thread {0} - End {1}", Thread.CurrentThread.ManagedThreadId, num);
}
public static List<Task> TaskList = new List<Task>();
public static void Main(string[] args)
{
for (int i = 0; i < 3; i++)
{
int idx = i;
TaskList.Add(Task.Factory.StartNew(() => Foo(idx)));
}
Task.WaitAll(TaskList.ToArray());
}
}
- Pourquoi faites-vous cela dans une Application Console? Il n'y a pas de contexte (par défaut), donc
await
a tendance à se comporter étrangement, de toute façon... - Quels sont exactement vous attendent à voir dans la console? Comment est-ce différent de ce que vous voyez?
- Ce que j'attends de voir sont six lignes montrant à la fois Début et de Fin de chaque tâche. Mais pour l'instant, j'en vois seulement de Commencer...
- Votre code semble fonctionner pour moi ... (s'exécutant dans un wpf solution, mais encore, le code fonctionne, une fois que la fin s'exécute sur le thread GUI...)
async void
méthode que vous passez àTask.Factory.StartNew
est une mauvaise idée. Vous ne pouvez pas garder une trace de la tâche en attente, il commence ou attraper toutes les exceptions qu'il peut jeter aprèsawait
. Cochez cette pour plus d'info: stackoverflow.com/q/19747910/1768303
Vous devez vous connecter pour publier un commentaire.
Est-ce que vous essayez d'atteindre?
De sortie:
async void
. Aussi, assurez-vous de lire Stephen Toub du blog ce qui concerne l'imbrication des tâches, c'est très instructif.La chose à prendre en compte est que parce que Foo est asynchrone, il est lui-même une Tâche. Votre exemple a des tâches qui, tout simplement, le coup d'envoi de la
Foo
tâche, mais n'attendez pas pour cela.En d'autres termes,
Task.WaitAll(TaskList.ToArray())
est simplement en attente pour chaqueTask.Delay
pour commencer, mais il n'est pas d'attente pour l'ensemble de ces tâches pour terminer.Ce pourrait bien être ce que vous essayez d'atteindre:
J'ai testé, et il produit la sortie de la console que vous visez.
La principale différence ici est que nous allons appeler
Task.Run
au lieu deTask.Factory.StartNew
.Vous pourriez avoir un
Task
qui renvoie unTask
, qui pourrait revenir un autreTask
. On pourrait penser à cela comme une "chaîne" des tâches.Task.Run
renvoie uneTask
qui représentent la tâche finale de la chaîne. Lorsque vous attendez pour cela, vous êtes en attente pour la chaque maillon de la chaîne de tâches à réaliser.En comparaison,
Task.Factory.StartNew
retourne une tâche qui représente le premier maillon de la chaîne. Après avoir attendu pour elle, vous êtes de gauche avec le reste de la chaîne d'attendre. C'est bien dans la grande majorité des cas où laTask
renvoie à quelque chose qui n'est pas un autreTask
.Task.Run
automatiquement le déballe, ce qui est inutile, de l'OMI. Sinon, le code semble pas être différente de la version que j'ai proposée. Ne sais pas si c'est ce que l'OP veut.