47 votes

Visual Studio Async CTP - Comment cela fonctionne-t-il ?

Microsoft a annoncé le Visual Studio Async CTP aujourd'hui (28 octobre 2010) qui présente la async y await en C#/VB pour l'exécution de méthodes asynchrones.

J'ai d'abord pensé que le compilateur traduisait les mots-clés en la création d'un thread, mais selon l'indicateur livre blanc et Anders Hejlsberg Présentation du PDC (à 31:00) l'opération asynchrone se déroule entièrement sur le thread principal.

Comment puis-je faire exécuter une opération en parallèle sur le même thread ? Comment est-ce techniquement possible et en quoi cette fonctionnalité est-elle réellement traduite en IL ?

84voto

Tomas Petricek Points 118959

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.

49voto

Eric Lippert Points 300275

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

Tu ne peux pas. L'asynchronie n'est pas le "parallélisme" ou la "concurrence". . L'asynchronisme peut être mis en œuvre avec le parallélisme, ou ne pas l'être. Elle peut être mise en œuvre en divisant le travail en petits morceaux, en plaçant chaque morceau de travail dans une file d'attente, puis en exécutant chaque morceau de travail lorsque le thread ne fait rien d'autre.

J'ai rédigé toute une série d'articles sur mon blog pour expliquer comment tout cela fonctionne. Celui qui concerne directement cette question sera probablement publié jeudi prochain. Regardez

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

pour les détails.

8voto

Brian Rasmussen Points 68853

Si je comprends bien, ce que le async y await Les mots-clés font que chaque fois qu'un async utilise la méthode await le compilateur transformera le reste de la méthode en une continuation qui sera planifiée lorsque l'opération asynchrone sera terminée. Cela permet async pour revenir immédiatement à l'appelant et reprendre le travail lorsque la partie asynchrone est terminée.

Selon les documents disponibles, il y a beaucoup de détails, mais sauf erreur de ma part, c'est l'essentiel.

De mon point de vue, le but des méthodes asynchrones n'est pas d'exécuter beaucoup de code en parallèle, mais de découper les méthodes asynchrones en un certain nombre de petits morceaux, qui peuvent être appelés selon les besoins. Le point clé est que le compilateur se chargera de tout le câblage complexe des callbacks en utilisant des tâches/continuations. Cela réduit non seulement la complexité, mais permet aux méthodes asynchrones d'être écrites plus ou moins comme du code synchrone traditionnel.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X