2010-10-28 11 views
43

Microsoft gab heute (28. Oktober 2010) die Visual Studio Async CTP bekannt, die die Schlüsselwörter async und await in C#/VB für die asynchrone Methodenausführung einführt.C# Async - Wie funktioniert es?

Zuerst dachte ich, dass der Compiler die Schlüsselwörter in die Erstellung eines Threads übersetzt, aber gemäß der white paper und Anders Hejlsbergs PDC presentation (um 31:00) die asynchrone Operation geschieht vollständig auf dem Haupt-Thread.

Wie kann ich eine Operation parallel auf demselben Thread ausführen lassen? Wie ist es technisch möglich und was ist das Feature in IL?

Antwort

73

Es funktioniert ähnlich wie das Schlüsselwort yield return in C# 2.0.

Eine asynchrone Methode ist keine gewöhnliche sequentielle Methode. Es wird in eine Zustandsmaschine (ein Objekt) mit einem bestimmten Zustand kompiliert (lokale Variablen werden in Felder des Objekts umgewandelt). Jeder Codeblock zwischen zwei Verwendungen von await ist ein "Schritt" der Zustandsmaschine.

Dies bedeutet, dass beim Starten der Methode nur der erste Schritt ausgeführt wird und dann die Zustandsmaschine zurückkehrt und einige zu erledigende Aufgaben einplant - wenn die Arbeit erledigt ist, wird der nächste Schritt der Zustandsmaschine ausgeführt. Zum Beispiel dieser Code:

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

möchte etwas übersetzt werden:

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); 
    } 
} 

Der wichtigste Teil ist, dass es nur die SetContinuation Methode verwendet, um anzugeben, dass, wenn der Vorgang abgeschlossen ist, sollte es die Step nennen Methode (und die Methode weiß, dass das zweite Bit des ursprünglichen Codes mit dem Feld _state ausgeführt werden soll). Sie können sich leicht vorstellen, dass die SetContinuation so etwas wie btn.Click += Step wäre, die komplett auf einem einzigen Thread laufen würde. Das asynchrone Programmiermodell in C# ähnelt sehr den asynchronen F # -Arbeitsabläufen (abgesehen von einigen technischen Details ist es im Wesentlichen dasselbe) und das Schreiben reaktiver single-threaded-GUI-Anwendungen unter Verwendung von async ist ein ziemlich interessanter Bereich - zumindest denke ich - siehe zum Beispiel this article (vielleicht sollte ich jetzt eine C# Version schreiben :-)).

Die Übersetzung ähnelt Iteratoren (und yield return) und tatsächlich war es möglich, Iteratoren zu verwenden, um die asynchrone Programmierung in C# früher zu implementieren. Ich schrieb vor einer Weile an article about that - und ich denke, dass es Ihnen noch einige Einblicke geben kann, wie die Übersetzung funktioniert.

6

Wie ich es verstehe, was die async und await Schlüsselwörter zu tun ist, dass jedes Mal, wenn eine async Methode, um das await Schlüsselwort verwendet, wird der Compiler den Rest des Verfahrens in eine Fortsetzung drehen, die geplant wird, wenn der Asynchron-Vorgang abgeschlossen ist. Das ermöglicht async Methoden, sofort zum Anrufer zurückzukehren und Arbeit fortzusetzen, wenn der Async-Teil fertig ist.

Nach den verfügbaren Papieren gibt es eine Menge Details, aber wenn ich nicht irre, ist das der Kern davon.

Wie ich es sehe, ist der Zweck der asynchronen Methoden nicht, viel Code parallel zu betreiben, sondern asynchrone Methoden in eine Anzahl kleiner Teile zu zerlegen, die nach Bedarf aufgerufen werden können. Der entscheidende Punkt ist, dass der Compiler die komplexe Verkabelung von Callbacks mit Tasks/Fortsetzungen übernimmt. Dies reduziert nicht nur die Komplexität, sondern ermöglicht es, asynchrone Methoden mehr oder weniger wie herkömmliche synchrone Codes zu schreiben.

+2

Wie ist es ohne einen separaten Thread geplant? Ist eine Fortsetzung ein spezifisches Konzept in der CLR, das eine leichte Planung erlaubt? –

+0

@ 0xA3: Ich glaube, das Papier sagt, dass die Async-Methode nicht auf einem eigenen Thread läuft. I.e. genau wie TPL wird es eine Mischung aus den aktuellen Thread- und Thread-Pool-Threads sein, abhängig von der Situation. –

43

Wie kann ich eine Operation parallel auf demselben Thread ausführen lassen?

Sie können nicht. Asynchronität ist nicht "Parallelität" oder "Nebenläufigkeit". Asynchronität kann mit Parallelität implementiert werden oder nicht. Es kann implementiert werden, indem die Arbeit in kleine Stücke zerlegt wird, jedes Stück Arbeit in eine Warteschlange gestellt wird und dann jedes Stück Arbeit ausgeführt wird, wenn der Thread zufällig nichts anderes tut.

Ich habe eine ganze Reihe von Artikeln in meinem Blog darüber, wie all das Zeug funktioniert; derjenige, der direkt mit dieser Frage zu tun hat, wird wahrscheinlich Donnerstag nächste Woche aufsteigen.

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

für weitere Details sehen.