Async Support Overview (Übersicht über die asynchrone Unterstützung)

C# 5 hat zwei Schlüsselwort (keyword) eingeführt, um die asynchrone Programmierung zu vereinfachen: asynchron und warten. Mit diesen Schlüsselwort (keyword)s können Sie einfachen Code schreiben, der die Task Parallel Library verwendet, um lange ausgeführte Vorgänge (z. B. Netzwerkzugriff) in einem anderen Thread auszuführen und problemlos auf die Ergebnisse nach Abschluss zuzugreifen. Die neuesten Versionen von Xamarin.iOS und Xamarin.Android unterstützen asynchron und warten - dieses Dokument enthält Erläuterungen und ein Beispiel für die Verwendung der neuen Syntax mit Xamarin.

Die Async-Unterstützung von Xamarin basiert auf der Mono 3.0-Foundation und aktualisiert das API-Profil von der mobilen Version von Silverlight auf eine mobile Version von .NET 4.5.

Überblick

In diesem Dokument werden die neuen Asynchronen vorgestellt und Schlüsselwort (keyword) werden dann einige einfache Beispiele für die Implementierung asynchroner Methoden in Xamarin.iOS und Xamarin.Android erläutert.

Eine ausführlichere Erläuterung der neuen asynchronen Features von C# 5 (einschließlich vieler Beispiele und verschiedener Verwendungsszenarien) finden Sie im Artikel "Asynchrone Programmierung".

Die Beispielanwendung erstellt eine einfache asynchrone Webanforderung (ohne den Standard Thread zu blockieren), und aktualisiert dann die Benutzeroberfläche mit der heruntergeladenen HTML- und Zeichenanzahl.

The sample application makes a simple asynchronous web request without blocking the main thread then updates the UI with the downloaded html and character count

Die asynchrone Unterstützung von Xamarin basiert auf der Mono 3.0-Foundation und aktualisiert das API-Profil von einer mobilen, benutzerfreundlichen Version von Silverlight auf eine mobile Version von .NET 4.5.

Anforderungen

C# 5-Features erfordern Mono 3.0, das in Xamarin.iOS 6.4 und Xamarin.Android 4.8 enthalten ist. Sie werden aufgefordert, Ihr Mono,Xamarin.iOS, Xamarin.Android und Xamarin.Mac zu aktualisieren, um es zu nutzen.

Verwenden von async & await

asyncund await sind neue C#-Sprachfeatures, die in Verbindung mit der Task Parallel Library funktionieren, um das Schreiben von Threadcode zu vereinfachen, um lang ausgeführte Aufgaben auszuführen, ohne den Standard Thread Ihrer Anwendung zu blockieren.

async

Deklaration

Die async Schlüsselwort (keyword) wird in einer Methodendeklaration (oder in einer Lambda- oder anonymen Methode) platziert, um anzugeben, dass sie Code enthält, der asynchron ausgeführt werden kann, d. h. nicht den Thread des Aufrufers blockieren.

Eine mit async einer Methode markierte Methode sollte mindestens einen await-Ausdruck oder eine Anweisung enthalten. Wenn keine await Anweisungen in der Methode vorhanden sind, wird sie synchron ausgeführt (identisch mit dem, wenn kein async Modifizierer vorhanden wäre). Dies führt auch zu einer Compilerwarnung (aber nicht zu einem Fehler).

Rückgabetypen

Eine asynchrone Methode sollte ein Task, Task<TResult> oder void.

Geben Sie den Task Rückgabetyp an, wenn die Methode keinen anderen Wert zurückgibt.

Geben Sie an Task<TResult> , ob die Methode einen Wert zurückgeben muss, wobei TResult der Typ zurückgegeben wird (z. B. ein intBeispiel).

Der void Rückgabetyp wird Standard für Ereignishandler verwendet, die dies erfordern. Code, der asynchrone Methoden mit void-returning aufruft, kann für das Ergebnis nicht await ausgeführt werden.

Parameter

Asynchrone Methoden können weder deklarieren noch out Parameter.ref

await

Der Await-Operator kann auf eine Aufgabe innerhalb einer als asynchron gekennzeichneten Methode angewendet werden. Die Methode bewirkt, dass die Ausführung an diesem Punkt beendet wird, und warten Sie, bis die Aufgabe abgeschlossen ist.

Die Verwendung von Await blockiert nicht den Thread des Aufrufers. Stattdessen wird das Steuerelement an den Aufrufer zurückgegeben. Dies bedeutet, dass der aufrufende Thread nicht blockiert ist, sodass beispielsweise der Benutzeroberflächenthread beim Warten auf eine Aufgabe nicht blockiert wird.

Nach Abschluss der Aufgabe wird die Ausführung der Methode an dem gleichen Punkt im Code fortgesetzt. Dies schließt die Rückkehr zum Try-Scope eines try-catch-finally-Blocks ein (sofern vorhanden). await cannot be used in a catch or finally block.

Weitere Informationen zu await.

Ausnahmebehandlung

Ausnahmen, die innerhalb einer asynchronen Methode auftreten, werden in der Aufgabe gespeichert und ausgelöst, wenn die Aufgabe ed wird await. Diese Ausnahmen können in einem Try-Catch-Block abgefangen und behandelt werden.

Abbruch

Asynchrone Methoden, die eine lange Zeit in Anspruch nehmen, sollten den Abbruch unterstützen. In der Regel wird der Abbruch wie folgt aufgerufen:

  • Es wird ein CancellationTokenSource Objekt erstellt.
  • Die CancellationTokenSource.Token Instanz wird an eine abbruchbare asynchrone Methode übergeben.
  • Der Abbruch wird durch Aufrufen der CancellationTokenSource.Cancel Methode angefordert.

Die Aufgabe bricht sich dann selbst ab und bestätigt den Abbruch.

Weitere Informationen zum Abbrechen finden Sie unter Fine-Tuning Your Async Application (C#) (Abstimmen der asynchronen Anwendung (C#)).

Beispiel

Laden Sie die Xamarin-Beispiellösung (für iOS und Android) herunter, um ein funktionierendes Beispiel für async und await in mobilen Apps anzuzeigen. Der Beispielcode wird in diesem Abschnitt ausführlicher erläutert.

Schreiben einer asynchronen Methode

Die folgende Methode veranschaulicht, wie eine async Methode mit einer awaited-Aufgabe codiert wird:

public async Task<int> DownloadHomepage()
{
    var httpClient = new HttpClient(); // Xamarin supports HttpClient!

    Task<string> contentsTask = httpClient.GetStringAsync("https://visualstudio.microsoft.com/xamarin"); // async method!

    // await! control returns to the caller and the task continues to run on another thread
    string contents = await contentsTask;

    ResultEditText.Text += "DownloadHomepage method continues after async call. . . . .\n";

    // After contentTask completes, you can calculate the length of the string.
    int exampleInt = contents.Length;

    ResultEditText.Text += "Downloaded the html and found out the length.\n\n\n";

    ResultEditText.Text += contents; // just dump the entire HTML

    return exampleInt; // Task<TResult> returns an object of type TResult, in this case int
}

Beachten Sie Folgendes:

  • Die Methodendeklaration enthält die async Schlüsselwort (keyword).
  • Der Rückgabetyp ist Task<int> so, dass der aufrufende Code auf den wert zugreifen kann, der int in dieser Methode berechnet wird.
  • Die Return-Anweisung ist return exampleInt; ein ganzzahliges Objekt – die Tatsache, dass die Methode zurückgegeben Task<int> wird, ist Teil der Sprachverbesserungen.

Aufrufen einer asynchronen Methode 1

Dieser Click-Ereignishandler für Schaltflächen befindet sich in der Android-Beispielanwendung, um die oben beschriebene Methode aufzurufen:

GetButton.Click += async (sender, e) => {

    Task<int> sizeTask = DownloadHomepage();

    ResultTextView.Text = "loading...";
    ResultEditText.Text = "loading...\n";

    // await! control returns to the caller
    var intResult = await sizeTask;

    // when the Task<int> returns, the value is available and we can display on the UI
    ResultTextView.Text = "Length: " + intResult ;
    // "returns" void, since it's an event handler
};

Hinweise:

  • Der anonyme Delegat hat das asynchrone Schlüsselwort (keyword) Präfix.
  • Die asynchrone Methode DownloadHomepage gibt einen Task<int> zurück, der in der SizeTask-Variablen gespeichert ist.
  • Der Code wartet auf die SizeTask-Variable. Dies ist der Speicherort, an dem die Methode angehalten wird, und das Steuerelement wird an den aufrufenden Code zurückgegeben, bis die asynchrone Aufgabe im eigenen Thread abgeschlossen ist.
  • Die Ausführung wird nicht angehalten, wenn die Aufgabe in der ersten Zeile der Methode erstellt wird, obwohl die Aufgabe dort erstellt wurde. Das Await Schlüsselwort (keyword) zeigt den Speicherort an, an dem die Ausführung angehalten wird.
  • Wenn die asynchrone Aufgabe abgeschlossen ist, wird intResult festgelegt und die Ausführung wird im ursprünglichen Thread von der Await-Zeile fortgesetzt.

Aufrufen einer asynchronen Methode 2

In der iOS-Beispielanwendung wird das Beispiel etwas anders geschrieben, um einen alternativen Ansatz zu veranschaulichen. Anstatt einen anonymen Delegaten zu verwenden, deklariert dieses Beispiel einen async Ereignishandler, der wie ein regulärer Ereignishandler zugewiesen wird:

GetButton.TouchUpInside += HandleTouchUpInside;

Die Ereignishandlermethode wird dann wie hier gezeigt definiert:

async void HandleTouchUpInside (object sender, EventArgs e)
{
    ResultLabel.Text = "loading...";
    ResultTextView.Text = "loading...\n";

    // await! control returns to the caller
    var intResult = await DownloadHomepage();

    // when the Task<int> returns, the value is available and we can display on the UI
    ResultLabel.Text = "Length: " + intResult ;
}

Einige wichtige Punkte:

  • Die Methode wird als async aber zurückgegeben void markiert. Dies erfolgt in der Regel nur für Ereignishandler (andernfalls geben Sie ein Task oder Task<TResult> ) zurück.
  • Die await Schlüsselwort (keyword) für die DownloadHomepage Methode weist eine Variable (intResult) direkt zu, im Gegensatz zum vorherigen Beispiel, in dem wir eine Zwischenvariable Task<int> verwendet haben, um auf den Vorgang zu verweisen. Dies ist der Ort, an dem das Steuerelement an den Aufrufer zurückgegeben wird, bis die asynchrone Methode in einem anderen Thread abgeschlossen wurde.
  • Wenn die asynchrone Methode abgeschlossen und zurückgegeben wird, wird die Ausführung an der Stelle fortgesetzt, an der await das ganze Ergebnis zurückgegeben und dann in einem UI-Widget gerendert wird.

Zusammenfassung

Die Verwendung von asynchronen und await vereinfacht den Code erheblich, der zum Spawnen von lang ausgeführten Vorgängen in Hintergrundthreads erforderlich ist, ohne den Standard Thread zu blockieren. Sie erleichtern auch den Zugriff auf die Ergebnisse, wenn die Aufgabe abgeschlossen wurde.

Dieses Dokument hat einen Überblick über die neue Sprache Schlüsselwort (keyword) und Beispiele für Xamarin.iOS und Xamarin.Android gegeben.