web-dev-qa-db-fra.com

ne peut pas attendre lambda async

Considère ceci,

Task task = new Task (async () =>{
    await TaskEx.Delay(1000);
});
task.Start();
task.Wait(); 

L'appel task.Wait () n'attend pas l'achèvement de la tâche et la ligne suivante est exécutée immédiatement, mais si j'emballe l'expression lambda asynchrone dans un appel de méthode, le code fonctionne comme prévu.

private static async Task AwaitableMethod()
{
    await TaskEx.Delay(1000);    
}

then (mis à jour en fonction du commentaire de svick)

await AwaitableMethod(); 
61
kennyzx

Dans votre exemple lambda, lorsque vous appelez task.Wait(), vous attendez la nouvelle tâche que vous avez construite, et non la tâche différée renvoyée. Pour obtenir le délai souhaité, vous devez également attendre la tâche résultante:

Task<Task> task = new Task<Task>(async () => {
    await Task.Delay(1000);
});
task.Start();
task.Wait(); 
task.Result.Wait();

Vous pouvez éviter de construire une nouvelle tâche et ne gérer qu'une tâche au lieu de deux:

Func<Task> task = async () => {
    await TaskEx.Delay(1000);
};
task().Wait();
82
Joe Daley

Vous devez utiliser TaskEx.RunEx.

Il prend en charge en natif l'exécution de méthodes async sur le TaskPool en attendant la tâche interne en interne. Sinon, vous rencontrerez le problème auquel vous êtes confronté, où seule la tâche externe est attendue, qui se termine évidemment immédiatement, en laissant soit une tâche qui reste à attendre, soit, dans votre cas (et même pire) un vide lambda qui ne peut pas être attendu.

Sinon, vous pouvez attendre la tâche deux fois, à condition de construire correctement votre tâche externe (ce que vous n'êtes pas en train de faire).

Code actuel (corrigé):

Task task = new Task<Task>(async () =>{
    await TaskEx.Delay(1000);
});

task.Start();
var innerTask = await task;
await innerTask;

Utiliser TaskEx.RunEx:

Task task = TaskEx.RunEx(async () =>{ // Framework awaits your lambda internally.
    await TaskEx.Delay(1000);
});

await task;
6