2013-06-07 11 views
6

Ich habe über C# Async-Methoden in den letzten 2 Tagen gelesen und von dem, was ich verstehe, im Gegensatz zu einem Thread (threadpool.queueuserworkitem()), ein Aufruf an eine asynchrone Methode nicht sofort zurück und es gibt nur zurück, wenn die aufgerufene Methode hits a wait oder complete (oder exception)Async Programmierung Steuerung Fluss

Bitte beachten Sie das folgende Beispiel.

public partial class MainWindow : Window 
{ 
    // . . . 
    private async void startButton_Click(object sender, RoutedEventArgs e) 
    { 
     // ONE 
     Task<int> getLengthTask = AccessTheWebAsync(); 

     // FOUR 
     int contentLength = await getLengthTask; 

     // SIX 
     resultsTextBox.Text += 
      String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength); 
    } 


    async Task<int> AccessTheWebAsync() 
    { 
     // TWO 
     HttpClient client = new HttpClient(); 
     Task<string> getStringTask = 
      client.GetStringAsync("http://msdn.microsoft.com"); 

     // THREE     
     string urlContents = await getStringTask; 

     // FIVE 
     return urlContents.Length; 
    } 
} 

Von dem, was ich sammeln, in dem obigen Code, AccessTheWebAsync() synchron aufgerufen wird (d. Steuerung nicht sofort zurück, wenn sie aufgerufen wird). In der Zeile "DREI" gibt die Laufzeit die Kontrolle zurück.

Meine Fragen sind:

  1. Wie wirkt sich die Laufzeit entscheiden, wann die Threadpool zu verwenden, oder wenn die Aufgabe in der anrufenden Thread laufen? (d. h. den Code ausführen, ohne die Kontrolle zurückzugeben)

  2. An welchen Punkten im obigen Code werden neue Threads (oder Threadpools) verwendet?

  3. Wenn AccessTheWebAsync() etwas rechenintensiv durchgeführt hat, z. B. das Ausführen einer Schleife mit einer Zillion Iterationen, kehrt das Steuerelement erst zum Aufrufer zurück, wenn die Schleife abgeschlossen ist. Ist das richtig?

  4. In einer asynchronen Funktion gibt es eine Möglichkeit, die Steuerung sofort zurückzugeben und dann die Arbeit in einem Hintergrund-Thread fortzusetzen? (Genau wie wenn wir threadpool.queueuserworkitem() aufrufen würden)

  5. Ruft eine asynchrone Methode ohne Wartezeit darauf auf (angenommen, es ist möglich), genauso wie das Aufrufen einer nicht asynchronen Methode?

Antwort

6

Zuerst etwas Wichtiges: Die Laufzeit wird wieder nur an den Anrufer auf await, wenn die Aufgabe hat, zu erwarten sei noch nicht abgeschlossen.

Frage 1: Ich werde die MSDN hier zitieren:

Die async und warten Keywords erstellt keine zusätzlichen Threads verursachen werden. Async-Methoden erfordern kein Multithreading, da eine asynchrone Methode nicht in einem eigenen Thread ausgeführt wird.

Source

Frage 2: Vielleicht bei der Umsetzung der GetStringAsync aber wir wissen nicht, dass und wir müssen es auch nicht wissen. Es ist genug für uns zu wissen, dass GetStringAsync irgendwie sein Ergebnis erhält, ohne unseren Thread zu blockieren.

Frage 3: Wenn die Schleife vor dem Schlüsselwort await platziert wird, ja.

Frage 4: Zitat aus dem gleichen Absatz wie zuvor:

Sie Task.Run verwenden können CPU-gebundene Arbeit zu einem Hintergrund-Thread

Sie die async brauchen nicht zu bewegen, und await Schlüsselwörter dafür.Beispiel:

private Task<int> DoSomethingAsync() 
{ 
    return Task.Run(() => 
    { 
     // Do CPU heavy calculation here. It will be executed in the thread pool. 
     return 1 + 1; 
    }); 
} 

Frage 5: Ich werde zitieren wieder

Ein asynchrones Verfahren enthält typischerweise ein oder mehrere Vorkommen eines await Operator, aber das Fehlen erwarten Ausdrücke verursacht keine Compiler-Fehler . Wenn eine Async-Methode keinen Warteoperator verwendet, um einen Aufhängungspunkt zu markieren, wird die Methode trotz des Async-Modifikators als synchrone Methode ausgeführt. Der Compiler gibt eine Warnung für solche Methoden aus.

Source (gleiche Seite wie zuvor, nur ein anderer Abschnitt)

3

Wie wirkt sich die Laufzeit entscheiden, wann die Threadpool zu verwenden, oder wenn die Aufgabe in der anrufenden Thread laufen?

Wenn es einen Zusammenhang Synchronisation ist und Sie nicht explizit angeben Sie nicht auf den Kontext fortsetzen wollen (durch so etwas wie await task.ConfigureAwait(false) verwendet wird), dann wird das Verfahren auf dem erfassten Kontext fortzusetzen. In UI-Anwendungen ist dieser Kontext der UI-Thread, vorausgesetzt, die Methode wird über den UI-Thread aufgerufen.

An welchen Stellen im obigen Code werden neue Threads (oder Threadpools) verwendet?

Nirgendwo. Sofern Sie nichts anderes angeben (siehe oben), wird await mit dem erfassten Kontext fortgesetzt, was in Ihrem Fall der UI-Thread ist.

Wenn AccessTheWebAsync() etwas tat rechenintensiv, wie eine Schleife mit zig Wiederholungen ausgeführt wird, wird die Steuerung nur an den Anrufer zurück, wenn die Schleife beendet ist. Ist das richtig?

Ja, vorausgesetzt, die Schleife war vor dem ersten "asynchronen" await. (await kann auch „synchron“, wenn der await ed Task bereits abgeschlossen ist.)

In einer Asynchron-Funktion gibt es eine Möglichkeit, die Steuerung sofort zurück und dann weiter zu tun, die Arbeit in etwa einem Hintergrund-Thread?

Sie sollten Task.Run() dafür verwenden.

Ruft eine asynchrone Methode ohne Wartezeit auf (angenommen, es ist möglich), genauso wie das Aufrufen einer nicht asynchronen Methode?

Es ist möglich und der Compiler warnt Sie, dass die Methode vollständig synchron ausgeführt wird.