que se passe-t-il si j’attends une tâche déjà en cours d’exécution?

Il y a une variable Task et disons que la tâche est en cours d’exécution .. en exécutant la ligne suivante.

await _task; 

Je me demandais ce qui se passe quand j’écris ce code:

 await _task; await _task; 

exécuterait-il la tâche deux fois? Ou jeter une exception parce qu’il a déjà été exécuté?

exécuterait-il la tâche deux fois? Ou jeter une exception parce qu’il a déjà été exécuté?

Non et non La seule chose à faire est d’appeler Task.GetAwaiter , cela ne provoque aucune exécution. Si la tâche est déjà terminée jusqu’à son terme, elle extrait la valeur s’il s’agit d’une Task ou s’exécute de manière synchrone sur la ligne suivante s’il s’agit d’une Task car il existe une optimisation pour les tâches déjà terminées.

Une simple démo:

 async Task Main() { var foo = FooAsync(); await foo; await foo; var bar = BarAsync(); var firstResult = await bar; var secondResult = await bar; Console.WriteLine(firstResult); Console.WriteLine(secondResult); } public async Task FooAsync() { await Task.Delay(1); } public async Task BarAsync() { await Task.Delay(1); return 1; } 

Si vous explorez la machine d’état elle-même, vous verrez ceci:

 this.5__1 = this.<>4__this.FooAsync(); taskAwaiter = this.5__1.GetAwaiter(); if (!taskAwaiter.IsCompleted) { this.<>1__state = 0; this.<>u__1 = taskAwaiter; M.d__0 d__ = this; this.<>t__builder.AwaitUnsafeOnCompletedd__0> (ref taskAwaiter, ref d__); return; } 

Cette optimisation vérifie d’abord l’achèvement de la tâche. Si la tâche n’est pas terminée, il appellera UnsafeOnCompleted qui enregistrera la suite. S’il est complet, l’ switch et passe à:

 this.<>1__state = -2; this.<>t__builder.SetResult(); 

Ce qui définit le résultat de la Task sous-jacente et permet d’obtenir la valeur de manière synchrone.

J’ai jeté ensemble ce test rapide:

 var i = 0; var task = Task.Run(() => { i++; Console.WriteLine(i); return i; }); var x = await task; var y = await task; Console.WriteLine(x); Console.WriteLine(y); 

Il écrit:

 1 1 1 

Donc, clairement, la tâche ne s’exécute qu’une fois.