Ablaufsteuerung in asynchronen Programmen (C# und Visual Basic)
Sie können asynchrone Programme leicht schreiben und beibehalten, indem Sie die Async und Await Schlüsselwörter verwenden.überraschten jedoch möglicherweise die Ergebnisse Sie, wenn Sie nicht wissen, wie das Programm funktioniert.Dieses Thema verfolgt den Programmablauf durch ein einfaches Programm asynchrones nach, um anzuzeigen, wenn das Steuerelement von einer Methode zu anderen verschoben wird und welche Informationen jedes Mal übertragen werden.
Hinweis |
---|
Die Async und Await Schlüsselwörter wurden in Visual Studio 2012 eingeführt.Weitere Informationen zu neuen Funktionen in dieser Version, finden Sie unter Neues in Visual Studio 2012. |
Im Allgemeinen Sie mark-Methoden, die asynchronen Code mit dem Async (Visual Basic) oder asynchron (C#)-Modifizierer enthalten.In einer Methode, die einem asynchronen Modifizierer markiert ist, können Sie einen Rechnen Sie (Visual Basic) oder Sie erwarten (C#)-Operator verwenden, um anzugeben, wo die Methode enthält, die auf einem aufgerufenen asynchronen Prozess zu warten, dass abzuschließen.Weitere Informationen finden Sie unter Asynchrone Programmierung mit Async und Await (C# und Visual Basic).
Im folgenden Beispiel wird asynchrone Methoden, um den Inhalt einer bestimmten Website als Zeichenfolge herunterzuladen und die Länge der Zeichenfolge anzuzeigen.Das Beispiel enthält die folgenden zwei Methoden.
startButton_Click, das AccessTheWebAsync aufruft und das Ergebnis anzeigt.
AccessTheWebAsync, das den Inhalt einer Website als Zeichenfolge Herunterladen und die Länge der Zeichenfolge zurückgibt.AccessTheWebAsync verwendet eine asynchrone Methode HttpClient, GetStringAsync(String), um den Inhalt herunterzuladen.
Nummerierte Bildzeilen scheinen an strategischen Punkten während des Programms, die Ihnen helfen, zu verstehen wie die Programmausführungen und zu berücksichtigen, was an jedem Punkt geschieht, der gekennzeichnet ist.Die Bildzeilen werden der Bezeichnung "Eine" durch "SECHS." Die Bezeichnungen stellen die Reihenfolge dar, in der das Programm diese Codezeilen erreicht.
Der folgende Code zeigt Kontur des Programms an.
Class MainWindow
Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) Handles StartButton.Click
' ONE
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
' FOUR
Dim contentLength As Integer = Await getLengthTask
' SIX
ResultsTextBox.Text &=
String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, contentLength)
End Sub
Async Function AccessTheWebAsync() As Task(Of Integer)
' TWO
Dim client As HttpClient = New HttpClient()
Dim getStringTask As Task(Of String) =
client.GetStringAsync("https://msdn.microsoft.com")
' THREE
Dim urlContents As String = Await getStringTask
' FIVE
Return urlContents.Length
End Function
End Class
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("https://msdn.microsoft.com");
// THREE
string urlContents = await getStringTask;
// FIVE
return urlContents.Length;
}
}
Jeder Speicherorte mit einer Bezeichnung "," durch "," SECHS zeigt Informationen über den aktuellen Zustand des Programms an.Die folgende Ausgabe erzeugt wird.
ONE: Entering startButton_Click.
Calling AccessTheWebAsync.
TWO: Entering AccessTheWebAsync.
Calling HttpClient.GetStringAsync.
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
Length of the downloaded string: 33946.
Installieren Sie das Programm
Sie können den Code herunterladen, den dieses Thema von MSDN verwendet, oder Sie können es selbst erstellen.
Hinweis |
---|
Um das Beispiel auszuführen, müssen Sie Visual Studio 2012, Visual Studio Express 2012 oder .NET Framework 4.5 enthalten, das auf dem Computer installiert ist. |
Laden Sie das Programm herunter
Sie können die Anwendung für dieses Thema von Asynchrones Beispiel: Ablaufsteuerung in asynchrone Programme herunterladen.Die folgenden Schritte öffnen und das Programm.
Entzippen Sie die heruntergeladene Datei, und starten Sie dann Visual Studio 2012.
Klicken Sie in der Menüleiste auf Datei, dann auf Öffnen und Projekt/Projektmappe.
Navigieren Sie zum Ordner, der den entzippten Beispielcode enthält, öffnen Sie die Projektmappendatei (.sln) und wählen dann die F5-Taste, um das Projekt zu erstellen und auszuführen.
Erstellen Sie das Programm auf
Im folgenden Projekt (Windows Presentation Foundation) enthält das Codebeispiel für dieses Thema.
Um das Projekt auszuführen, müssen Sie die folgenden Schritte aus:
Starten Sie Visual Studio.
Wählen Sie in der Menüleiste Datei, Neu, Projekt aus.
Das Dialogfeld Neues Projekt wird angezeigt.
Im Bereich Installierte Vorlagen wählen Sie Visual Basic oder Visual C# aus, und wählen Sie dann WPF-Anwendung aus der Liste der - Projekttypen aus.
Geben Sie AsyncTracer als Namen für das Projekt ein, und wählen Sie dann die Schaltfläche OK aus.
Das neue Projekt wird im Projektmappen-Explorer angezeigt.
In Visual Studio MainWindow.xaml wählen Sie die Registerkarte aus.
Wenn die Registerkarte nicht sichtbar ist, öffnen Sie das Kontextmenü für MainWindow.xaml in Projektmappen-Explorer, und wählen Sie dann Code anzeigen aus.
In der Ansicht XAML der Datei MainWindow.xaml, ersetzen Sie den Code durch den folgenden Code.
<Window xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="MainWindow" Title="Control Flow Trace" Height="350" Width="525"> <Grid> <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="221,10,0,0" VerticalAlignment="Top" Width="75"/> <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="510" Height="265" FontFamily="Lucida Console" FontSize="10" VerticalScrollBarVisibility="Visible" d:LayoutOverrides="HorizontalMargin"/> </Grid> </Window>
<Window xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="https://schemas.microsoft.com/expression/blend/2008" xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="AsyncTracer.MainWindow" Title="Control Flow Trace" Height="350" Width="592"> <Grid> <Button x:Name="startButton" Content="Start
" HorizontalAlignment="Left" Margin="250,10,0,0" VerticalAlignment="Top" Width="75" Height="24" Click="startButton_Click" d:LayoutOverrides="GridBox"/> <TextBox x:Name="resultsTextBox" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="576" Height="265" FontFamily="Lucida Console" FontSize="10" VerticalScrollBarVisibility="Visible" Grid.ColumnSpan="3"/> </Grid> </Window>
Ein einfaches Fenster, das ein Textfeld und eine Schaltfläche enthält, wird in der Ansicht Entwurf der Datei MainWindow.xaml.
Fügen Sie einen Verweis für System.Net.Http hinzu.
In Projektmappen-Explorer öffnen Sie das Kontextmenü für MainWindow.xaml.cs oder MainWindow.xaml.vb, und wählen Sie dann Code anzeigen aus.
Klicken Sie in "MainWindow.xaml.vb" oder ersetzen Sie den Code durch den folgenden Code.
' Add an Imports statement and a reference for System.Net.Http. Imports System.Net.Http Class MainWindow Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs) Handles StartButton.Click ' The display lines in the example lead you through the control shifts. ResultsTextBox.Text &= "ONE: Entering StartButton_Click." & vbCrLf & " Calling AccessTheWebAsync." & vbCrLf Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync() ResultsTextBox.Text &= vbCrLf & "FOUR: Back in StartButton_Click." & vbCrLf & " Task getLengthTask is started." & vbCrLf & " About to await getLengthTask -- no caller to return to." & vbCrLf Dim contentLength As Integer = Await getLengthTask ResultsTextBox.Text &= vbCrLf & "SIX: Back in StartButton_Click." & vbCrLf & " Task getLengthTask is finished." & vbCrLf & " Result from AccessTheWebAsync is stored in contentLength." & vbCrLf & " About to display contentLength and exit." & vbCrLf ResultsTextBox.Text &= String.Format(vbCrLf & "Length of the downloaded string: {0}." & vbCrLf, contentLength) End Sub Async Function AccessTheWebAsync() As Task(Of Integer) ResultsTextBox.Text &= vbCrLf & "TWO: Entering AccessTheWebAsync." ' Declare an HttpClient object. Dim client As HttpClient = New HttpClient() ResultsTextBox.Text &= vbCrLf & " Calling HttpClient.GetStringAsync." & vbCrLf ' GetStringAsync returns a Task(Of String). Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com") ResultsTextBox.Text &= vbCrLf & "THREE: Back in AccessTheWebAsync." & vbCrLf & " Task getStringTask is started." ' AccessTheWebAsync can continue to work until getStringTask is awaited. ResultsTextBox.Text &= vbCrLf & " About to await getStringTask & return a Task(Of Integer) to StartButton_Click." & vbCrLf ' Retrieve the website contents when task is complete. Dim urlContents As String = Await getStringTask ResultsTextBox.Text &= vbCrLf & "FIVE: Back in AccessTheWebAsync." & vbCrLf & " Task getStringTask is complete." & vbCrLf & " Processing the return statement." & vbCrLf & " Exiting from AccessTheWebAsync." & vbCrLf Return urlContents.Length End Function End Class
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; // Add a using directive and a reference for System.Net.Http; using System.Net.Http; namespace AsyncTracer { public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private async void startButton_Click(object sender, RoutedEventArgs e) { // The display lines in the example lead you through the control shifts. resultsTextBox.Text += "ONE: Entering startButton_Click.\r\n" + " Calling AccessTheWebAsync.\r\n"; Task<int> getLengthTask = AccessTheWebAsync(); resultsTextBox.Text += "\r\nFOUR: Back in startButton_Click.\r\n" + " Task getLengthTask is started.\r\n" + " About to await getLengthTask -- no caller to return to.\r\n"; int contentLength = await getLengthTask; resultsTextBox.Text += "\r\nSIX: Back in startButton_Click.\r\n" + " Task getLengthTask is finished.\r\n" + " Result from AccessTheWebAsync is stored in contentLength.\r\n" + " About to display contentLength and exit.\r\n"; resultsTextBox.Text += String.Format("\r\nLength of the downloaded string: {0}.\r\n", contentLength); } async Task<int> AccessTheWebAsync() { resultsTextBox.Text += "\r\nTWO: Entering AccessTheWebAsync."; // Declare an HttpClient object. HttpClient client = new HttpClient(); resultsTextBox.Text += "\r\n Calling HttpClient.GetStringAsync.\r\n"; // GetStringAsync returns a Task<string>. Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com"); resultsTextBox.Text += "\r\nTHREE: Back in AccessTheWebAsync.\r\n" + " Task getStringTask is started."; // AccessTheWebAsync can continue to work until getStringTask is awaited. resultsTextBox.Text += "\r\n About to await getStringTask and return a Task<int> to startButton_Click.\r\n"; // Retrieve the website contents when task is complete. string urlContents = await getStringTask; resultsTextBox.Text += "\r\nFIVE: Back in AccessTheWebAsync." + "\r\n Task getStringTask is complete." + "\r\n Processing the return statement." + "\r\n Exiting from AccessTheWebAsync.\r\n"; return urlContents.Length; } } }
Wählen Sie die F5-TASTE, um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start aus.
Die folgende Ausgabe sollte angezeigt werden.
ONE: Entering startButton_Click. Calling AccessTheWebAsync. TWO: Entering AccessTheWebAsync. Calling HttpClient.GetStringAsync. THREE: Back in AccessTheWebAsync. Task getStringTask is started. About to await getStringTask & return a Task<int> to startButton_Click. FOUR: Back in startButton_Click. Task getLengthTask is started. About to await getLengthTask -- no caller to return to. FIVE: Back in AccessTheWebAsync. Task getStringTask is complete. Processing the return statement. Exiting from AccessTheWebAsync. SIX: Back in startButton_Click. Task getLengthTask is finished. Result from AccessTheWebAsync is stored in contentLength. About to display contentLength and exit. Length of the downloaded string: 33946.
Vollziehen Sie das Programm nach
Eine Schritte und ZWEI
Die ersten beiden Bildzeilen vollziehen den Pfad, während startButton_ClickAccessTheWebAsync aufruft, und AccessTheWebAsync Aufrufe die asynchrone HttpClient-Methode GetStringAsync(String) nach.Im folgenden Bild wird die Aufrufe von Methode zu Methode.
Der Rückgabetyp von - AccessTheWebAsync und von client.GetStringAsync ist Task<TResult>.Für AccessTheWebAsync ist TResult eine ganze Zahl.Für GetStringAsync ist TResult eine Zeichenfolge.Weitere Informationen über asynchrone Methodenrückgabetypen, finden Sie unter Asynchrone Rückgabetypen (C# und Visual Basic).
Eine Aufgabe-zurückkehrende asynchrone Methode gibt eine Aufgabeninstanz wenn Steuerschichten zurück an den Aufrufer zurück.Steuerelement gibt von einer asynchronen Methode an dessen Aufrufer entweder zurück, wenn ein Await oder await-Operator in der aufgerufenen Methode erreicht wird, oder wenn die aufgerufene Methode beendet.Die Bildzeilen, die "DREI" durch "SECHS" Ablaufverfolgung diesen Teil des Prozesses bezeichnet werden.
Schritt 3
In AccessTheWebAsync wird die asynchrone Methode GetStringAsync(String) aufgerufen, um den Inhalt der Zielwebseite herunterzuladen.Steuerelement gibt von client.GetStringAsync zu AccessTheWebAsync zurück, wenn client.GetStringAsync zurückgibt.
Die client.GetStringAsync-Methode gibt eine Aufgabe der Zeichenfolge zurück, die zur getStringTask-Variable in AccessTheWebAsync zugewiesen wird.Die folgende Zeile im Beispielprogramm veranschaulicht client.GetStringAsync und der Zuweisung den Aufruf an.
Dim getStringTask As Task(Of String) = client.GetStringAsync("https://msdn.microsoft.com")
Task<string> getStringTask = client.GetStringAsync("https://msdn.microsoft.com");
Sie können an der Aufgabe als Zusicherung durch client.GetStringAsync vorstellen, eine tatsächliche Zeichenfolge dann zu erzeugen.Mittlerweile wenn AccessTheWebAsync die Arbeit hat, auszuführen, die nicht von der viele versprechenden Zeichenfolge aus client.GetStringAsync abhängt, kann diese Arbeit fortfahren, während client.GetStringAsync wartet.Im Beispiel stellen die folgenden Zeilen der Ausgabe, die "DREI bezeichnet werden," die Möglichkeit dar, unabhängige Aufgaben ausführt
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
Die folgende Anweisung enthält Status in AccessTheWebAsync an, wenn getStringTask erwartet wird.
Dim urlContents As String = Await getStringTask
string urlContents = await getStringTask;
Das folgende Bild zeigt den Kontrollfluss von client.GetStringAsync zur Zuweisung zu getStringTask und von der Erstellung von getStringTask zur Verwendung eines Erwartungsoperators an.
Der Erwartungsausdruck enthält AccessTheWebAsync an, bis client.GetStringAsync zurückgibt.Mittlerweile kehrt die Steuerung an den Aufrufer von AccessTheWebAsync, startButton_Click zurück.
Hinweis |
---|
In der Regel erwarten Sie den Aufruf einer asynchronen Methode sofort.Beispielsweise könnte eine der folgenden Zuweisungen den vorherigen Code ersetzen, der erstellt und dann getStringTask erwartet:
In diesem Thema wird der Erwartungsoperator später angewendet, um die Ausgabezeilen anzupassen, die die Ablaufsteuerung vom Programm markieren. |
Schritt 4
Der deklarierte Rückgabetyp von AccessTheWebAsync ist Task(Of Integer) in Visual Basic und in Task<int> in C#.Wenn AccessTheWebAsync angehalten wird, wird eine Aufgabe von ganzzahligen zu startButton_Click zurück.Sie wissen, dass die zurückgegebene Aufgabe nicht getStringTask ist.Die zurückgegebene Aufgabe ist eine neue Aufgabe der ganze Zahl, die, das in der angehaltenen Methode vorgenommen werden, bleibt AccessTheWebAsync darstellt.Die Aufgabe ist eine Zusicherung von AccessTheWebAsync, eine ganze Zahl zu erzeugen, wenn die Aufgabe abgeschlossen wurde.
Die folgende Anweisung ordnet diese Aufgabe zur getLengthTask-Variable zu.
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
Task<int> getLengthTask = AccessTheWebAsync();
Wie in AccessTheWebAsync, kann startButton_Click mit Arbeit fortfahren, die nicht aus den Ergebnissen der asynchronen Aufgabe (getLengthTask) abhängt bis die Aufgabe erwartet ist.Die folgenden Ausgabezeilen stellen diese Arbeit dar.
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
Status in startButton_Click wird angehalten, wenn getLengthTask erwartet wird.Die folgenden Zuweisungsanweisung enthält startButton_Click an, bis AccessTheWebAsync abgeschlossen ist.
Dim contentLength As Integer = Await getLengthTask
int contentLength = await getLengthTask;
In der folgenden Abbildung werden die Pfeile die Ablaufsteuerung vom Erwartungsausdruck in AccessTheWebAsync zur Zuweisung eines Werts zu getLengthTask an, gefolgt von dem normalen Verarbeitung in startButton_Click, bis getLengthTask erwartet ist.
Schritt 5
Wenn client.GetStringAsync signalisiert, dass es vollständig ist und in AccessTheWebAsync verarbeitet, von der Unterbrechung verwendet werden und Vergangenheit fortsetzen kann die Erwartungsanweisung.Die folgenden Zeilen der Ausgabe stellen die Wiederaufnahme der Verarbeitung dar.
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
Der Operand der return-Anweisung, urlContents.Length, wird in der Aufgabe gespeichert, die AccessTheWebAsync zurückgibt.Der Erwartungsausdruck ruft diesen Wert von getLengthTask in startButton_Click ab.
Das folgende Bild zeigt den Ablaufsprung nach client.GetStringAsync (und getStringTask) sind vollständig an.
AccessTheWebAsync wird vollständig ausgeführt und Steuerelement kehrt zu startButton_Click zurück, das den Abschluss erwartet.
Schritt SECHS
Wenn AccessTheWebAsync signalisiert, dass er vollständig ist und verarbeitet, Vergangenheit fortsetzen können die Erwartungsanweisung in startButton_Async.Tatsächlich hat das Programm nichts weiter durchzuführen.
Die folgenden Zeilen der Ausgabe stellen die Wiederaufnahme der Verarbeitung in startButton_Async dar:
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
Der Erwartungsausdruck ruft von getLengthTask den ganzzahligen Wert ab, der Operand der return-Anweisung in AccessTheWebAsync ist.Die folgende Anweisung weist den Wert zur contentLength-Variable zu.
Dim contentLength As Integer = Await getLengthTask
int contentLength = await getLengthTask;
Das folgende Bild zeigt die Rückgabe des Steuerelements von AccessTheWebAsync zu startButton_Click an.
Siehe auch
Aufgaben
Exemplarische Vorgehensweise: Zugreifen auf das Web mit Async und Await (C# und Visual Basic)
Exemplarische Vorgehensweise: Verwenden des Debuggers mit Async-Methoden
Konzepte
Asynchrone Programmierung mit Async und Await (C# und Visual Basic)
Asynchrone Rückgabetypen (C# und Visual Basic)
Weitere Ressourcen
Asynchrones Beispiel: Ablaufsteuerung in asynchrone Programme (C# und Visual Basic)