Il fonctionne de la même manière que le yield return
en C# 2.0.
Une méthode asynchrone n'est en fait pas une méthode séquentielle ordinaire. Elle est compilée dans une machine à états (un objet) avec un certain état (les variables locales sont transformées en champs de l'objet). Chaque bloc de code entre deux utilisations de await
est une "étape" de la machine à états.
Cela signifie que lorsque la méthode démarre, elle exécute la première étape, puis l'automate à états revient et planifie le travail à effectuer. Une fois le travail effectué, l'étape suivante de l'automate à états est exécutée. Par exemple, ce code :
async Task Demo() {
var v1 = foo();
var v2 = await bar();
more(v1, v2);
}
Cela se traduirait par quelque chose comme :
class _Demo {
int _v1, _v2;
int _state = 0;
Task<int> _await1;
public void Step() {
switch(this._state) {
case 0:
this._v1 = foo();
this._await1 = bar();
// When the async operation completes, it will call this method
this._state = 1;
op.SetContinuation(Step);
case 1:
this._v2 = this._await1.Result; // Get the result of the operation
more(this._v1, this._v2);
}
}
La partie importante est qu'elle utilise simplement le SetContinuation
pour spécifier que lorsque l'opération est terminée, elle doit appeler la méthode Step
(et la méthode sait qu'elle doit exécuter la deuxième partie du code original en utilisant la méthode _state
). Vous pouvez facilement imaginer que le SetContinuation
serait quelque chose comme btn.Click += Step
qui s'exécuterait entièrement sur un seul fil.
Le modèle de programmation asynchrone de C# est très proche des flux de travail asynchrones de F# (en fait, il s'agit essentiellement de la même chose, à quelques détails techniques près), et l'écriture d'applications GUI réactives à un seul thread à l'aide de async
est un domaine assez intéressant - du moins je le pense - voir par exemple cet article (je devrais peut-être écrire une version C# maintenant :-)).
La traduction est similaire à celle des itérateurs (et des yield return
) et en fait, il était possible d'utiliser les itérateurs pour mettre en œuvre la programmation asynchrone en C# auparavant. J'ai écrit un article à ce sujet il y a quelque temps - et je pense qu'il peut encore vous donner un aperçu de la façon dont la traduction fonctionne.