Quelqu'un pourrait-il avoir la gentillesse de confirmer si j'ai bien compris le mot clé Async wait? (Utilisation de la version 3 du CTP)
Jusqu'à présent, j'ai déterminé que l'insertion du mot clé wait avant un appel de méthode fait essentiellement 2 choses, A. Cela crée un retour immédiat et B. Il crée une "continuation" qui est invoquée à la fin de l'invocation de la méthode async. Dans tous les cas, la suite est le reste du bloc de code pour la méthode.
Donc, ce que je me demande, est-ce que ces deux bits de code sont techniquement équivalents, et si c'est le cas, cela signifie-t-il essentiellement que le mot-clé wait est identique à la création d'un ContinueWith Lambda (c'est-à-dire qu'il s'agit essentiellement d'un raccourci de compilation pour un)? Sinon, quelles sont les différences?
bool Success =
await new POP3Connector(
"mail.server.com", txtUsername.Text, txtPassword.Text).Connect();
// At this point the method will return and following code will
// only be invoked when the operation is complete(?)
MessageBox.Show(Success ? "Logged In" : "Wrong password");
CONTRE
(new POP3Connector(
"mail.server.com", txtUsername.Text, txtPassword.Text ).Connect())
.ContinueWith((success) =>
MessageBox.Show(success.Result ? "Logged In" : "Wrong password"));
L'idée générale est correcte - le reste de la méthode est transformée en une sorte de continuation.
Le article de blog "Fast Path" contient des détails sur le fonctionnement de la transformation du compilateur async
/await
.
Différences, du haut de ma tête:
Le mot clé await
utilise également un concept de "contexte de planification". Le contexte de planification est SynchronizationContext.Current
s'il existe, se replier sur TaskScheduler.Current
. La suite est ensuite exécutée sur le contexte de planification. Donc une approximation plus proche serait de passer TaskScheduler.FromCurrentSynchronizationContext
dans ContinueWith
, se repliant sur TaskScheduler.Current
si nécessaire.
L'implémentation réelle de async
/await
est basée sur la correspondance de modèles; il utilise un modèle "attendable" qui permet d'attendre d'autres choses que les tâches. Quelques exemples sont les API asynchrones WinRT, certaines méthodes spéciales telles que Yield
, observables Rx et attendables socket spéciaux qui ne frappent pas le GC aussi fort . Les tâches sont puissantes, mais elles ne sont pas les seules à attendre.
Une autre différence mineure me vient à l'esprit: si l'attente est déjà terminée, la méthode async
ne revient pas réellement à ce point; il continue de façon synchrone. C'est un peu comme passer TaskContinuationOptions.ExecuteSynchronously
, mais sans les problèmes liés à la pile.
C'est "essentiellement" cela, mais le code généré fait strictement plus que cela. Pour beaucoup plus de détails sur le code généré, je recommande fortement la série Eduasync de Jon Skeet:
http://codeblog.jonskeet.uk/category/eduasync/
En particulier, le post # 7 explique ce qui est généré (à partir de CTP 2) et pourquoi, donc probablement un bon ajustement pour ce que vous recherchez en ce moment:
http://codeblog.jonskeet.uk/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method/
EDIT: Je pense que cela sera probablement plus détaillé que ce que vous recherchez dans la question, mais si vous vous demandez à quoi les choses ressemblent lorsque vous avez plusieurs attentes dans la méthode, cela est couvert dans le post # 9 :)
http://codeblog.jonskeet.uk/2011/05/30/eduasync-part-9-generated-code-for-multiple-awaits/