2012-03-27 11 views
57

Zwei neue Keywords an der C# 5.0 Sprache hinzugefügt sind async und await, von denen beide Hand in Hand arbeiten, um eine C# Methode asynchron ohne Blockieren des anrufenden Thread ausgeführt.Verwenden die neuen C# 5.0-Async- und -Abfrage-Schlüsselwörter mehrere Kerne?

Meine Frage ist, nehmen diese Methoden tatsächlich die Vorteile von mehreren Kernen und laufen parallel oder tut das async Verfahren laufen im selben Thread Kern wie die Anrufer?

+5

Es hängt von dem erwarteten Objekt ab, das von der asynchronen Methode zurückgegeben wird. – phoog

+1

Weder. Sie sind nur Syntaxzucker. Threading hängt von dem aktuellen 'SynchronizationContext' und der' Task' ab, die Sie erwarten. – CodesInChaos

Antwort

93

Zwei neue Schlüsselwörter, die der C# 5.0-Sprache hinzugefügt wurden, sind async und warten darauf, dass beide Hand in Hand eine C# -Methode asynchron ausführen, ohne den aufrufenden Thread zu blockieren.

, die über den Zweck wird der Funktion, aber es gibt zu viel „Kredit“ zu der Asynchron/await Funktion.

Lassen Sie mich in diesem Punkt sehr, sehr klar sein: await verursacht nicht magisch eine synchrone Methode, um asynchron zu laufen. Es wird kein neuer Thread gestartet und die Methode zum Beispiel für den neuen Thread ausgeführt. Die Methode, die Sie aufrufen, muss die Sache sein, die sich selbst asynchron ausführen kann. Wie es sich dazu entscheidet, ist sein Geschäft.

Meine Frage ist, nutzen diese Methoden tatsächlich mehrere Kerne und laufen parallel oder läuft die Async-Methode im selben Thread-Kern wie der Aufrufer?

Nochmals, das ist ganz bis zu der Methode, die Sie anrufen. All das, was await tut, weist den Compiler an, die Methode in einen Delegaten neu zu schreiben, der als Fortsetzung der asynchronen Task übergeben werden kann. Das heißt, die await FooAsync() bedeutet „FooAsync() nennen und was auch immer kommt wieder etwas sein muss, die die asynchrone Operation darstellt, die gerade in Betrieb genommen. Das Ding Sagen Sie, dass, wenn es weiß, dass die asynchrone Operation durchgeführt wird, soll es diese Delegierten nennen.“ Der Delegat verfügt über die Eigenschaft, dass die aktuelle Methode nach dem Aufruf scheinbar "dort fortgesetzt wird, wo sie aufgehört hat".

Wenn die Methode Sie Pläne rufen auf einem anderen Thread arbeiten affinitize an einen anderen Kern, groß. Wenn es einen Timer startet, der in der Zukunft auf dem UI-Thread einige Ereignishandler pingt, großartig. await ist es egal. Alles was es tut, ist sicherzustellen, dass die Steuerung, wenn der asynchrone Job beendet ist, dort weiterarbeiten kann, wo sie aufgehört hat.

Eine Frage, die Sie nicht gefragt hat, aber wahrscheinlich haben sollte, ist:

Wenn die asynchrone Aufgabe beendet ist und die Steuerung nimmt, wo er aufgehört hat, ist die Ausführung im selben Thread wie es vorher war?

Es hängt vom Kontext ab. In einer Winforms-Anwendung, in der Sie etwas vom UI-Thread abwarten, wird die Steuerung im UI-Thread erneut gestartet. In einer Konsolenanwendung, vielleicht nicht.

+1

Ich mag deine Erklärung hier und es hilft mir wirklich, Async besser zu verstehen und zu erwarten. – Icemanind

+1

Wenn Sie etwas auf dem UIhread abwarten, wird das Steuerelement * normalerweise * im UI-Thread erneut aufgerufen, muss es aber nicht. Das hängt auch vom "Etwas ab, das die asynchrone Operation darstellt". Zum Beispiel passiert es, wenn Sie 'someTask.ConfigureAwait (false)' erwarten. – svick

2

Da async und await auf der TPL basieren, sollten sie sehr ähnlich funktionieren. Standardmäßig sollten Sie sie so behandeln, als würden sie in einem separaten Thread ausgeführt.

4

Eine asynchrone Methode gibt ein erwartetes Objekt zurück (eines mit einer GetAwaiter-Methode), und der Compiler kann Code zum Verwenden dieses Objekts generieren, wenn Sie die Methode mit dem Schlüssel await aufrufen. Sie sind auch frei, ein solches Verfahren das await Schlüsselwort ohne zu nennen, und das Objekt explizit verbrauchen.

Das Objekt kapselt eine asynchrone Aktion, die auf einem anderen Thread kann oder kann nicht ausgeführt werden. Eric Lippert Artikel Asynchrony in C# 5.0 part Four: It's not magic berücksichtigt ein Beispiel für asynchrone Programmierung, die nur einen Thread enthält.

65

Eric Lippert hat eine ausgezeichnete Antwort; Ich wollte nur async ein bisschen weiter beschreiben.

Die einfache „serial“ -Ansatz ist, wo Sie await nur eine Sache auf einmal:

static void Process() 
{ 
    Thread.Sleep(100); // Do CPU work. 
} 

static async Task Test() 
{ 
    await Task.Run(Process); 
    await Task.Run(Process); 
} 

In diesem Beispiel ist die Test Methode Process zum Thread-Pool Warteschlange wird, und wenn es vervollständigt wird es Warteschlange Process wieder in den Thread-Pool. Die Test Methode wird nach ~ 200ms abgeschlossen. Zu jeder Zeit bringt nur ein Thread den Fortschritt voran.

Ein einfacher Weg, dies zu parallelisieren ist Task.WhenAll zu verwenden: zweimal

static void Process() 
{ 
    Thread.Sleep(100); // Do CPU work. 
} 

static async Task Test() 
{ 
    // Start two background operations. 
    Task task1 = Task.Run(Process); 
    Task task2 = Task.Run(Process); 

    // Wait for them both to complete. 
    await Task.WhenAll(task1, task2); 
} 

In diesem Beispiel werden die Verfahren Test Warteschlangen Process zum Thread-Pool, und wartet dann, bis sie beide zu vervollständigen. Die Methode Test wird nach ~ 100 ms abgeschlossen.

Task.WhenAll (und Task.WhenAny) wurden mit async/await eingeführt, um einfache Parallelität zu unterstützen. Die TPL ist jedoch immer noch vorhanden, wenn Sie etwas fortgeschritteneres benötigen (echte CPU-gebundene parallele Verarbeitung ist besser für die TPL geeignet). TPL spielt gut mit async/await.

I Abdeckung grundlegende async Parallelität in meinem into to async blog post, sowie der "Kontext", dass Eric angespielt.

+1

Danke auch für diese Antwort! – Icemanind

+0

Stephen, du sagst 'TPL spielt gut mit async/erwarten'. Könnten Sie mich auf einige gute Informationen zu diesem speziellen Thema hinweisen? – Patrick

+0

@Patrick: Wenn Sie Parallelität * und * Asynchronität benötigen, überprüfen Sie TPL Dataflow. –