Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Mithilfe der asynchronen Programmierung können Sie Leistungsengpässe vermeiden und die Gesamtreaktionsfähigkeit Ihrer Anwendung verbessern. Herkömmliche Techniken zum Schreiben asynchroner Anwendungen können jedoch kompliziert sein, wodurch sie schwer zu schreiben, zu debuggen und zu verwalten sind.
Visual Studio 2012 hat einen vereinfachten Ansatz eingeführt, eine asynchrone Programmierung, die asynchrone Unterstützung in .NET Framework 4.5 und höher sowie in der Windows-Runtime nutzt. Der Compiler erledigt die schwierige Arbeit, die der Entwickler verwendet hat, und Ihre Anwendung behält eine logische Struktur bei, die dem synchronen Code ähnelt. Daher erhalten Sie alle Vorteile der asynchronen Programmierung mit einem Bruchteil des Aufwands.
Dieses Thema enthält eine Übersicht darüber, wann und wie asynchrone Programmierung verwendet wird, und enthält Links zu Supportthemen, die Details und Beispiele enthalten.
Async verbessert die Reaktionsfähigkeit
Asynchronie ist wichtig für Aktivitäten, die potenziell blockiert werden, z. B. wenn Ihre Anwendung auf das Web zugreift. Der Zugriff auf eine Webressource ist manchmal langsam oder verzögert. Wenn eine solche Aktivität innerhalb eines synchronen Prozesses blockiert wird, muss die gesamte Anwendung warten. In einem asynchronen Prozess kann die Anwendung mit anderen Arbeiten fortfahren, die nicht von der Webressource abhängig sind, bis der potenziell blockierende Vorgang abgeschlossen ist.
Die folgende Tabelle zeigt typische Bereiche, in denen die asynchrone Programmierung die Reaktionsfähigkeit verbessert. Die aufgeführten APIs aus .NET Framework 4.5 und windows-Runtime enthalten Methoden, die die asynchrone Programmierung unterstützen.
Anwendungsbereich | Unterstützen von APIs, die asynchrone Methoden enthalten |
---|---|
Webzugriff | HttpClient, SyndicationClient |
Arbeiten mit Dateien | StorageFile, StreamWriter, StreamReader, XmlReader |
Arbeiten mit Bildern | MediaCapture, BitmapEncoderBitmapDecoder |
WCF-Programmierung | Synchrone und asynchrone Vorgänge |
Asynchronität erweist sich als besonders wertvoll für Anwendungen, die auf den UI-Thread zugreifen, da in der Regel alle UI-bezogenen Aktivitäten denselben Thread gemeinsam nutzen. Wenn ein Prozess in einer synchronen Anwendung blockiert wird, werden alle blockiert. Ihre Anwendung reagiert vorübergehend nicht, und Sie könnten irrtümlicherweise schließen, dass sie fehlgeschlagen ist, obwohl sie gerade nur wartet.
Wenn Sie asynchrone Methoden verwenden, reagiert die Anwendung weiterhin auf die Benutzeroberfläche. Sie können beispielsweise die Größe eines Fensters ändern oder minimieren, oder Sie können die Anwendung schließen, wenn Sie nicht warten möchten, bis es abgeschlossen ist.
Der asynchrone Ansatz fügt das Äquivalent einer automatischen Übertragung zur Liste der Optionen hinzu, die Sie beim Entwerfen asynchroner Vorgänge auswählen können. Das heißt, Sie erhalten alle Vorteile der herkömmlichen asynchronen Programmierung, aber mit viel weniger Aufwand vom Entwickler.
Asynchrone Methoden sind einfacher zu schreiben
Die Schlüsselwörter "Async " und "Await " in Visual Basic sind das Herzstück der asynchronen Programmierung. Mithilfe dieser beiden Schlüsselwörter können Sie Ressourcen in .NET Framework oder der Windows-Runtime verwenden, um eine asynchrone Methode fast so einfach zu erstellen, wie Sie eine synchrone Methode erstellen. Asynchrone Methoden, die Sie mithilfe von Async
und Await
definieren, werden als asynchrone Methoden bezeichnet.
Das folgende Beispiel zeigt eine asynchrone Methode. Fast alles im Code sollte Ihnen völlig vertraut sein. Die Kommentare nennen die Features, die Sie zum Erstellen der Asynchronie hinzufügen.
Sie finden eine vollständige Windows Presentation Foundation (WPF)-Beispieldatei am Ende dieses Themas, und Sie können das Beispiel aus Async-Beispiel herunterladen: Beispiel aus "Asynchrone Programmierung mit Async und Await".
' Three things to note about writing an Async Function:
' - The function has an Async modifier.
' - Its return type is Task or Task(Of T). (See "Return Types" section.)
' - As a matter of convention, its name ends in "Async".
Async Function AccessTheWebAsync() As Task(Of Integer)
Using client As New HttpClient()
' Call and await separately.
' - AccessTheWebAsync can do other things while GetStringAsync is also running.
' - getStringTask stores the task we get from the call to GetStringAsync.
' - Task(Of String) means it is a task which returns a String when it is done.
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://learn.microsoft.com/dotnet")
' You can do other work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork()
' The Await operator suspends AccessTheWebAsync.
' - AccessTheWebAsync does not continue until getStringTask is complete.
' - Meanwhile, control returns to the caller of AccessTheWebAsync.
' - Control resumes here when getStringTask is complete.
' - The Await operator then retrieves the String result from getStringTask.
Dim urlContents As String = Await getStringTask
' The Return statement specifies an Integer result.
' A method which awaits AccessTheWebAsync receives the Length value.
Return urlContents.Length
End Using
End Function
Wenn AccessTheWebAsync
keine Arbeit zwischen dem Aufruf von GetStringAsync
und dem Abwarten auf dessen Abschluss durchführen kann, können Sie Ihren Code vereinfachen, indem Sie den Aufruf und das Abwarten in der folgenden einzigen Anweisung zusammenfassen.
Dim urlContents As String = Await client.GetStringAsync()
Die folgenden Merkmale fassen zusammen, was das vorherige Beispiel zu einer asynchronen Methode macht:
Die Methodensignatur enthält einen
Async
Modifizierer.Der Name einer asynchronen Methode endet nach Konvention mit einem "Async"-Suffix.
Der Rückgabetyp ist einer der folgenden Typen:
- Task(Of TResult), wenn Ihre Methode eine Rückgabeanweisung hat, in der der Operand den Typ TResult hat.
- Task wenn die Methode keine Rückgabe-Anweisung hat oder eine Rückgabe-Anweisung ohne Operand aufweist.
- Sub , wenn Sie einen asynchronen Ereignishandler schreiben.
Weitere Informationen finden Sie weiter unten in diesem Thema unter "Rückgabetypen und Parameter".
Die Methode enthält in der Regel mindestens einen Await-Ausdruck, der einen Punkt markiert, an dem die Methode erst fortgesetzt werden kann, wenn der erwartete asynchrone Vorgang abgeschlossen ist. In der Zwischenzeit wird die Methode angehalten, und die Steuerung kehrt zum Aufrufer der Methode zurück. Im nächsten Abschnitt dieses Themas wird veranschaulicht, was am Unterbrechungspunkt geschieht.
In asynchronen Methoden verwenden Sie die bereitgestellten Schlüsselwörter und Typen, um anzugeben, was Sie tun möchten, und der Compiler erledigt den Rest, einschließlich des Nachverfolgens, was passieren muss, wenn das Steuerelement zu einem Wartepunkt in einer angehaltenen Methode zurückkehrt. Einige Routineprozesse, z. B. Schleifen und Ausnahmebehandlung, können im herkömmlichen asynchronen Code schwer behandelt werden. In einer asynchronen Methode schreiben Sie diese Elemente ähnlich wie in einer synchronen Lösung, und das Problem wird gelöst.
Weitere Informationen zur Asynchronie in früheren Versionen von .NET Framework finden Sie unter "TPL" und "Traditional .NET Framework Asynchronous Programming".
Was geschieht in einer Async-Methode
Das Wichtigste bei der asynchronen Programmierung ist, wie der Steuerungsfluss von Methode zu Methode verschoben wird. Das folgende Diagramm führt Sie durch den Prozess:
Die Zahlen im Diagramm entsprechen den folgenden Schritten:
Ein Ereignishandler ruft die
AccessTheWebAsync
asynchrone Methode auf und wartet darauf.AccessTheWebAsync
erstellt eine HttpClient Instanz und ruft die GetStringAsync asynchrone Methode auf, um den Inhalt einer Website als Zeichenfolge herunterzuladen.Etwas passiert in
GetStringAsync
, das seinen Fortschritt aussetzt. Vielleicht muss es darauf warten, dass eine Website heruntergeladen wird oder eine andere blockierende Tätigkeit beendet ist. Um das Blockieren von Ressourcen zu vermeiden,GetStringAsync
übergibt die Steuerung an seinen Aufrufer,AccessTheWebAsync
.GetStringAsync
gibt einen Task(Of TResult) zurück, wobei TResult eine Zeichenfolge ist undAccessTheWebAsync
die Aufgabe dergetStringTask
Variablen zuweist. Die Aufgabe stellt den laufenden Prozess für den Aufruf vonGetStringAsync
dar, mit der Festlegung, dass bei Abschluss der Arbeit ein tatsächlicher Zeichenfolgenwert erzeugt wurde.Da
getStringTask
noch nicht abgewartet wurde, kannAccessTheWebAsync
mit anderen Aufgaben fortfahren, die nicht vom Endergebnis vonGetStringAsync
abhängig sind. Diese Arbeit wird durch einen Aufruf der synchronen MethodeDoIndependentWork
dargestellt.DoIndependentWork
ist eine synchrone Methode, die ihre Arbeit ausführt und zum Aufrufer zurückkehrt.AccessTheWebAsync
hat keine Arbeit mehr, die es ohne ein Ergebnis vongetStringTask
erledigen kann.AccessTheWebAsync
als Nächstes möchte die Methode die Länge der heruntergeladenen Zeichenfolge berechnen und zurückgeben, aber sie kann diesen Wert erst berechnen, wenn sie die Zeichenfolge erhält.Daher verwendet
AccessTheWebAsync
einen Await-Operator, um seinen Fortschritt auszusetzen und die Kontrolle an die aufrufendeAccessTheWebAsync
-Methode zu übergeben.AccessTheWebAsync
gibt einenTask(Of Integer)
an den Aufrufer zurück. Die Aufgabe stellt eine Zusage dar, um ein ganzzahliges Ergebnis zu erzeugen, das die Länge der heruntergeladenen Zeichenfolge darstellt.Hinweis
Wenn
GetStringAsync
(und dahergetStringTask
) abgeschlossen wird, bevorAccessTheWebAsync
darauf wartet, verbleibt die Steuerung inAccessTheWebAsync
. Die Kosten für das Aussetzen und anschließende Zurückkehren zuAccessTheWebAsync
wären verschwendet, wenn der aufgerufene asynchrone Prozess (getStringTask
) bereits abgeschlossen ist und AccessTheWebSync nicht auf das endgültige Ergebnis warten müsste.Innerhalb des Aufrufers (der Ereignishandler in diesem Beispiel) wird das Verarbeitungsmuster fortgesetzt. Der Anrufer könnte andere Arbeiten ausführen, die nicht vom Ergebnis
AccessTheWebAsync
abhängig sind, bevor er darauf wartet, oder der Anrufer könnte sofort darauf warten. Der Ereignishandler wartet aufAccessTheWebAsync
, undAccessTheWebAsync
wartet aufGetStringAsync
.GetStringAsync
vervollständigt und liefert ein Ergebnis als Zeichenfolge. Das Zeichenfolgenergebnis wird vom AufrufGetStringAsync
nicht wie erwartet zurückgegeben. (Denken Sie daran, dass die Methode bereits einen Vorgang in Schritt 3 zurückgegeben hat.) Stattdessen wird das Zeichenfolgenergebnis in der Aufgabe gespeichert, die den Abschluss der Methode darstellt.getStringTask
Der await-Operator ruft das Ergebnis vongetStringTask
ab. Die Zuweisungsanweisung weist das abgerufene ErgebnisurlContents
zu.Wenn
AccessTheWebAsync
das Zeichenfolgenergebnis vorliegt, kann die Methode die Länge der Zeichenfolge berechnen. Dann ist die Arbeit vonAccessTheWebAsync
auch abgeschlossen, und der wartende Ereignishandler kann fortfahren. Im vollständigen Beispiel am Ende des Themas können Sie überprüfen, ob der Ereignishandler den Wert des Längenergebnisses abruft und druckt.
Wenn Sie neu in der asynchronen Programmierung sind, nehmen Sie sich einen Moment Zeit, um den Unterschied zwischen synchronem und asynchronem Verhalten zu verstehen. Eine synchrone Methode gibt zurück, wenn ihre Arbeit abgeschlossen ist (Schritt 5), aber eine asynchrone Methode gibt einen Vorgangswert zurück, wenn die Arbeit angehalten wird (Schritte 3 und 6). Wenn die asynchrone Methode schließlich ihre Arbeit abgeschlossen hat, wird die Aufgabe als abgeschlossen markiert, und das Ergebnis (falls vorhanden) wird in der Aufgabe gespeichert.
Weitere Informationen zum Steuerungsfluss finden Sie unter "Steuerungsfluss in Asynchronen Programmen (Visual Basic)".
API Async-Methoden
Möglicherweise fragen Sie sich, wo Sie Methoden wie GetStringAsync
finden, die die asynchrone Programmierung unterstützen. Die .NET Framework 4.5 oder höher enthält viele Elemente, die mit Async
und Await
arbeiten. Sie können diese Member durch das Suffix "Async" erkennen, das an den Membernamen angefügt ist, sowie einem Rückgabetyp von Task oder Task(Of TResult). Die Klasse, z. B., enthält Methoden wie System.IO.Stream
, CopyToAsync und ReadAsync neben den synchronen Methoden WriteAsync, CopyTo und Read.
Die Windows-Runtime enthält auch viele Methoden, die Sie mit Async
und Await
in Windows-Apps verwenden können. Weitere Informationen und Beispielmethoden finden Sie unter Aufrufen asynchroner APIs in C# oder Visual Basic, asynchroner Programmierung (Windows-Runtime-Apps) und WhenAny: Bridging zwischen .NET Framework und der Windows-Runtime.
Fäden
Asynchrone Methoden sollen nicht blockierende Vorgänge sein. Ein Await
Ausdruck in einer asynchronen Methode blockiert den aktuellen Thread nicht, während die erwartete Aufgabe ausgeführt wird. Stattdessen meldet der Ausdruck den Rest der Methode als Fortsetzung an und gibt die Kontrolle an den Aufrufer der asynchronen Methode zurück.
Die Async
Schlüsselwörter Await
führen nicht dazu, dass zusätzliche Threads erstellt werden. Asynchrone Methoden erfordern kein Multithreading, da eine asynchrone Methode nicht in einem eigenen Thread ausgeführt wird. Die Methode wird im aktuellen Synchronisierungskontext ausgeführt und verwendet nur Zeit auf dem Thread, wenn die Methode aktiv ist. Sie können Task.Run verwenden, um CPU-gebundene Arbeit in einen Hintergrundthread zu verschieben, aber ein Hintergrundthread hilft nicht bei einem Prozess, der nur darauf wartet, dass die Ergebnisse verfügbar sind.
Der auf Asynchronität basierende Ansatz ist in fast jedem Fall den vorhandenen Ansätzen vorzuziehen. Insbesondere eignet sich dieser Ansatz besser für E/A-gebundene Vorgänge als BackgroundWorker, da der Code einfacher ist und kein Schutz vor Racebedingungen erforderlich ist. In Kombination mit Task.Run ist die asynchrone Programmierung besser als BackgroundWorker für CPU-gebundene Vorgänge, da sie die Koordinationsdetails des Ausführens von Code von der Arbeit trennt, die Task.Run
an den Threadpool übertragen wird.
Async und Await
Wenn Sie angeben, dass eine Methode eine asynchrone Methode ist, indem Sie einen Asynchronen Modifizierer verwenden, aktivieren Sie die folgenden beiden Funktionen.
Die markierte asynchrone Methode kann Await verwenden, um Anhaltepunkte festzulegen. Der Await-Operator teilt dem Compiler mit, dass die asynchrone Methode nicht über diesen Punkt fortgesetzt werden kann, bis der erwartete asynchrone Prozess abgeschlossen ist. In der Zwischenzeit geht die Kontrolle an den Aufrufer der asynchronen Methode zurück.
Das Anhalten einer asynchronen Methode bei einem
Await
Ausdruck stellt keine Beendigung der Methode dar, undFinally
Blöcke werden nicht ausgeführt.Auf die markierte Async-Methode können auch Methoden warten, die sie aufrufen.
Eine asynchrone Methode enthält in der Regel ein oder mehrere Vorkommen eines Await
Operators, aber das Fehlen von Await
Ausdrücken verursacht keinen Compilerfehler. Wenn eine asynchrone Methode keinen Operator zum Markieren eines Anhaltepunkts verwendet Await
, wird die Methode trotz des Async
Modifizierers als synchrone Methode ausgeführt. Der Compiler gibt eine Warnung für solche Methoden aus.
Async
und Await
sind kontextbezogene Schlüsselwörter. Weitere Informationen und Beispiele finden Sie in den folgenden Themen:
Rückgabetypen und Parameter
Bei der .NET Framework-Programmierung gibt eine asynchrone Methode in der Regel eine Task oder eine Task(Of TResult)-Methode zurück. Innerhalb einer asynchronen Methode wird ein Await
Operator auf eine Aufgabe angewendet, die von einem Aufruf an eine andere asynchrone Methode zurückgegeben wird.
Sie geben Task(Of TResult) als Rückgabetyp an, wenn die Methode eine Return-Anweisung enthält, die einen Operanden vom Typ TResult
angibt.
Sie verwenden Task
als Rückgabetyp, wenn die Methode keine Rückgabe-Anweisung hat oder eine Rückgabe-Anweisung hat, die keinen Operanden zurückgibt.
Das folgende Beispiel zeigt, wie Sie eine Methode deklarieren und aufrufen, die entweder eine Task(Of TResult) oder ein Task zurückgibt.
' Signature specifies Task(Of Integer)
Async Function TaskOfTResult_MethodAsync() As Task(Of Integer)
Dim hours As Integer
' . . .
' Return statement specifies an integer result.
Return hours
End Function
' Calls to TaskOfTResult_MethodAsync
Dim returnedTaskTResult As Task(Of Integer) = TaskOfTResult_MethodAsync()
Dim intResult As Integer = Await returnedTaskTResult
' or, in a single statement
Dim intResult As Integer = Await TaskOfTResult_MethodAsync()
' Signature specifies Task
Async Function Task_MethodAsync() As Task
' . . .
' The method has no return statement.
End Function
' Calls to Task_MethodAsync
Task returnedTask = Task_MethodAsync()
Await returnedTask
' or, in a single statement
Await Task_MethodAsync()
Jede zurückgegebene Aufgabe stellt laufende Arbeit dar. Eine Aufgabe umfasst Informationen über den Status des asynchronen Prozesses und schließlich entweder das endgültige Ergebnis des Prozesses oder die Fehlerausnahme, die der Prozess auslöst, falls er nicht erfolgreich ist.
Eine asynchrone Methode kann auch eine Sub
Methode sein. Dieser Rückgabetyp wird in erster Linie verwendet, um Ereignishandler zu definieren, bei denen ein Rückgabetyp erforderlich ist. Asynchrone Ereignishandler dienen häufig als Ausgangspunkt für asynchrone Programme.
Eine asynchrone Methode, bei der es sich um eine Sub
-Prozedur handelt, kann nicht abgewartet werden, und der Aufrufer kann keine Ausnahmen erfassen, die die Methode auswirft.
Eine asynchrone Methode kann ByRef-Parameter nicht deklarieren, aber die Methode kann Methoden aufrufen, die über solche Parameter verfügen.
Weitere Informationen und Beispiele finden Sie unter Async-Rückgabetypen (Visual Basic). Weitere Informationen zum Auffangen von Ausnahmen in async-Methoden finden Sie unter Try...Catch...Finally Statement (Try...Catch...Finally-Anweisung).
Asynchrone APIs in der Windows-Runtime-Programmierung weisen einen der folgenden Rückgabetypen auf, die mit Aufgaben vergleichbar sind:
- IAsyncOperation(Of TResult), die Task(Of TResult) entspricht
- IAsyncAction, das entspricht Task
- IAsyncActionWithProgress(von TProgress)
- IAsyncOperationWithProgress(von TResult, TProgress)
Weitere Informationen und ein Beispiel finden Sie unter Aufrufen asynchroner APIs in C# oder Visual Basic.
Namenskonvention
Standardmäßig fügen Sie "Async" an die Namen von Methoden an, die über einen Async
Modifizierer verfügen.
Sie können die Konvention ignorieren, in der ein Ereignis, eine Basisklasse oder ein Schnittstellenvertrag einen anderen Namen vorschlägt. Zum Beispiel sollten Sie keine allgemeinen Ereignishandler wie Button1_Click
umbenennen.
Verwandte Themen und Beispiele (Visual Studio)
Vollständiges Beispiel
Der folgende Code ist die MainWindow.xaml.vb Datei aus der Windows Presentation Foundation (WPF)-Anwendung, die in diesem Thema erläutert wird. Sie können das Beispiel aus dem Async-Beispiel herunterladen: Beispiel aus "Asynchrone Programmierung mit Async und Await".
Imports System.Net.Http
' Example that demonstrates Asynchronous Programming with Async and Await.
' It uses HttpClient.GetStringAsync to download the contents of a website.
' Sample Output:
' Working . . . . . . .
'
' Length of the downloaded string: 39678.
Class MainWindow
' Mark the event handler with Async so you can use Await in it.
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
' Call and await immediately.
' StartButton_Click suspends until AccessTheWebAsync is done.
Dim contentLength As Integer = Await AccessTheWebAsync()
ResultsTextBox.Text &= $"{vbCrLf}Length of the downloaded string: {contentLength}.{vbCrLf}"
End Sub
' Three things to note about writing an Async Function:
' - The function has an Async modifier.
' - Its return type is Task or Task(Of T). (See "Return Types" section.)
' - As a matter of convention, its name ends in "Async".
Async Function AccessTheWebAsync() As Task(Of Integer)
Using client As New HttpClient()
' Call and await separately.
' - AccessTheWebAsync can do other things while GetStringAsync is also running.
' - getStringTask stores the task we get from the call to GetStringAsync.
' - Task(Of String) means it is a task which returns a String when it is done.
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://learn.microsoft.com/dotnet")
' You can do other work here that doesn't rely on the string from GetStringAsync.
DoIndependentWork()
' The Await operator suspends AccessTheWebAsync.
' - AccessTheWebAsync does not continue until getStringTask is complete.
' - Meanwhile, control returns to the caller of AccessTheWebAsync.
' - Control resumes here when getStringTask is complete.
' - The Await operator then retrieves the String result from getStringTask.
Dim urlContents As String = Await getStringTask
' The Return statement specifies an Integer result.
' A method which awaits AccessTheWebAsync receives the Length value.
Return urlContents.Length
End Using
End Function
Sub DoIndependentWork()
ResultsTextBox.Text &= $"Working . . . . . . .{vbCrLf}"
End Sub
End Class