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.
Übersicht
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.
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
async
und 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 int
Beispiel).
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 das Beispiel (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 await
ed-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, derint
in dieser Methode berechnet wird. - Die Return-Anweisung ist
return exampleInt;
ein ganzzahliges Objekt – die Tatsache, dass die Methode zurückgegebenTask<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ückgegebenvoid
markiert. Dies erfolgt in der Regel nur für Ereignishandler (andernfalls geben Sie einTask
oderTask<TResult>
) zurück. - Die
await
Schlüsselwort (keyword) für dieDownloadHomepage
Methode weist eine Variable (intResult
) direkt zu, im Gegensatz zum vorherigen Beispiel, in dem wir eine ZwischenvariableTask<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.
Verwandte Links
- Rückrufe als Go To-Erklärung unserer Generationen
- MapKitSearch (iOS) (Beispiel)
- Asynchrone Programmierung
- Feinabstimmung der Async-Anwendung (C#)
- Await, and UI, and deadlocks! Oh, mein!
- Verarbeiten von Aufgaben während der Ausführung)
- Aufgabenbasiertes asynchrones Muster (TAP, Task-based Asynchronous Pattern)
- Asynchrony in C# 5 (Eric Lipperts Blog) – über die Einführung der Schlüsselwort (keyword)