Comportement différent async / attend dans presque les mêmes méthodes

Disons que j’ai deux méthodes asynchrones

public async static Task RunAsync1() { await Task.Delay(2000); await Task.Delay(2000); } 

et

 public async static Task RunAsync2() { var t1 = Task.Delay(2000); var t2 = Task.Delay(2000); await t1; await t2; } 

Ensuite, je l’utilise comme

 public static void M() { RunAsync1().GetAwaiter().GetResult(); RunAsync2().GetAwaiter().GetResult(); } 

Dans un résultat, RunAsync1 exécutera 4sec mais RunAsync2 seulement 2sec
Quelqu’un peut-il expliquer pourquoi? Les méthodes sont presque les mêmes. Quelle est la différence?

Dans la seconde méthode, 2 tâches sont démarrées en même temps. Ils finiront tous les deux en 2 secondes (car ils courent en parallèle). Dans la première méthode, vous exécutez une méthode (2 secondes), attendez la fin, puis démarrez la seconde (2 secondes supplémentaires). Le point clé ici est Task.Delay(..) commence dès que vous l’appelez, pas quand vous l’attendez.

Pour clarifier davantage, première méthode:

 var t1 = Task.Delay(2000); // this task is running now await t1; // returns 2 seconds later var t2 = Task.Delay(2000); // this task is running now await t2; // returns 2 more seconds later 

Deuxième méthode:

 var t1 = Task.Delay(2000); var t2 = Task.Delay(2000); // both are running now await t1; // returns in about 2 seconds await t2; // returns almost immediately, because t2 is already running for 2 seconds 

Examinez votre code:

 public async static Task RunAsync1() { await Task.Delay(2000); // Start a delay task, and WAIT for it to finish await Task.Delay(2000); // Start a delay task, and WAIT for it to finish } 

La seconde await Task.Delay(2000); est appelé après la fin du premier appel (après 2 secondes).

Alors que la deuxième méthode,

 public async static Task RunAsync2() { var t1 = Task.Delay(2000); // Start a task var t2 = Task.Delay(2000); // Start a task await t1; // Wait for task to finish await t2; // Wait for task to finish } 

Donc, les tâches t1 et t2 s’exécutent en même temps.

Si vous le changez en

 public async static Task RunAsync3() { var t1 = Task.Delay(2000); // Start a task await t1; // Wait for task to finish var t2 = Task.Delay(2000); // Start a task await t2; // Wait for task to finish } 

vous obtiendrez les mêmes résultats que dans RunAsync1.

Dans le premier cas, vous dites

 public async static Task RunAsync1() { var t1 = Task.Delay(2000); await t1; var t2 = await Task.Delay(2000); await t2; } 

Ce qui équivaut à

  1. 0:00 Créer un rappel en 2 secondes 0:00
  2. 0:00 Attendez que le rappel soit revenu 0:02
  3. 0:02 Créer un rappel en 2 secondes 0:02
  4. 0:02 Attendez que le rappel soit revenu 0:04
  5. 0:04 retour;

Le deuxième cas est

 public async static Task RunAsync2() { var t1 = Task.Delay(2000); var t2 = Task.Delay(2000); await t1; await t2; } 
  1. 0:00 Créer des rappels en 2 secondes 0:00
  2. 0:00 Créer des rappels en 2 secondes 0:00
  3. 0:00 Attendre le premier rappel 0:02
  4. 0:02 Attendez le deuxième rappel 0:02
  5. 0:02 retour

En d’autres termes, dans le premier cas, vous effectuez une programmation asynchrone séquentielle et le second est une programmation asynchrone parallèle.

Chaque fois que vous démarrez une tâche. Cela a déjà commencé lorsque vous l’avez créé, pas lorsque vous avez appelé await .

Si vous créez une tâche et la mettez dans une variable, il est possible qu’elle se termine déjà lorsque vous l’attendez. C’est ce qui arrive à votre deuxième cas. await s’assure juste qu’il doit finir avant de continuer.