2010-10-28 7 views
43

Microsoft a annoncé le Visual Studio Async CTP aujourd'hui (28 octobre 2010) qui introduit les mots-clés async et await dans C#/VB pour l'exécution de méthode asynchrone.C# Async - Comment ça marche?

D'abord, je pensais que le compilateur traduit les mots clés dans la création d'un fil, mais selon la PDC presentation de white paper et Anders Hejlsberg (à 31:00) l'opération asynchrone se produit complètement sur le thread principal.

Comment exécuter une opération en parallèle sur le même thread? Comment est-ce techniquement possible et quelle est la fonctionnalité réellement traduite en IL?

Répondre

73

Il fonctionne de manière similaire au mot-clé yield return dans C# 2.0.

Une méthode asynchrone n'est pas réellement une méthode séquentielle ordinaire. Il est compilé dans une machine d'état (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 d'état. Cela signifie que lorsque la méthode démarre, elle exécute simplement la première étape, puis la machine d'état renvoie et planifie un travail à effectuer. Lorsque le travail est terminé, elle exécute l'étape suivante de la machine d'état. Par exemple, ce code:

async Task Demo() { 
    var v1 = foo(); 
    var v2 = await bar(); 
    more(v1, v2); 
} 

sera traduit à 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); 
    } 
} 

L'important est qu'il utilise juste la méthode SetContinuation de préciser que lorsque l'opération est terminée, il doit appeler la Step méthode à nouveau (et la méthode sait qu'il devrait exécuter le second bit du code original en utilisant le champ _state). Vous pouvez facilement imaginer que le SetContinuation serait quelque chose comme btn.Click += Step, qui fonctionnerait complètement sur un seul thread. Le modèle de programmation asynchrone en C# est très proche des workflows asynchrones F # (en fait, c'est essentiellement la même chose, mis à part quelques détails techniques), et l'écriture d'applications GUI monothread réactives en utilisant async est une zone assez intéressante - au moins je le pense - voir par exemple this article (peut-être que je devrais écrire une version C# maintenant :-)).

La traduction est similaire aux itérateurs (et yield return) et en fait, il était possible d'utiliser des itérateurs pour implémenter la programmation asynchrone en C# plus tôt. J'ai écrit an article about that il y a quelques temps - et je pense que cela peut encore vous donner un aperçu de la façon dont la traduction fonctionne.

6

Si je comprends bien, ce que les async et await mots-clés font est que chaque fois qu'une méthode async utilise le mot-clé await, le compilateur tourner le reste de la méthode dans une poursuite qui est prévue lorsque l'opération asynchrone est terminée. Cela permet aux méthodes async de retourner immédiatement à l'appelant et de reprendre le travail lorsque la partie asynchrone est terminée. Selon les documents disponibles, il y a beaucoup de détails, mais à moins que je me trompe, c'est l'essentiel. Comme je le vois, les méthodes asynchrones n'ont pas pour but d'exécuter beaucoup de code en parallèle, mais de couper les méthodes asynchrones en un certain nombre de petits morceaux, qui peuvent être appelés au besoin. Le point clé est que le compilateur gérera tout le câblage complexe des rappels en utilisant des tâches/continuations. Cela réduit non seulement la complexité, mais permet à la méthode async d'être écrite plus ou moins comme le code synchrone traditionnel.

+2

Comment est-il programmé sans thread séparé? Une continuation est-elle un concept spécifique dans le CLR qui permet une planification légère? –

+0

@ 0xA3: Je crois que le document dit que la méthode async ne fonctionne pas sur son propre thread. C'est à dire. Tout comme TPL, il s'agira d'un mélange des threads actuels du thread et du pool de threads en fonction de la situation. –

43

Comment exécuter une opération en parallèle sur le même thread?

Vous ne pouvez pas. L'asynchronisme n'est pas un "parallélisme" ou une "simultanéité". L'asynchronie peut être implémentée avec le parallélisme, ou peut-être pas. Il pourrait être implémenté en décomposant le travail en petits morceaux, en mettant chaque morceau de travail sur une file d'attente, puis en exécutant chaque morceau de travail chaque fois que le fil arrive à ne rien faire d'autre.

J'ai toute une série d'articles sur mon blog sur la façon dont tout cela fonctionne; celui directement lié à cette question remontera probablement jeudi de la semaine prochaine. Regarder

http://blogs.msdn.com/b/ericlippert/archive/tags/async/

pour plus de détails.