Kontrollflöde i Async-program (Visual Basic)
Du kan skriva och underhålla asynkrona program enklare med hjälp av nyckelorden Async
och Await
. Resultatet kan dock överraska dig om du inte förstår hur programmet fungerar. Det här avsnittet spårar kontrollflödet via ett enkelt asynkront program för att visa dig när kontrollen flyttas från en metod till en annan och vilken information som överförs varje gång.
Kommentar
Nyckelorden Async
och Await
introducerades i Visual Studio 2012.
I allmänhet markerar du metoder som innehåller asynkron kod med Async-modifieraren . I en metod som är markerad med en asynkron modifierare kan du använda operatorn Await (Visual Basic) för att ange var metoden pausar för att vänta tills en så kallad asynkron process har slutförts. Mer information finns i Asynkron programmering med Async och Await (Visual Basic).
I följande exempel används asynkrona metoder för att ladda ned innehållet på en angiven webbplats som en sträng och för att visa längden på strängen. Exemplet innehåller följande två metoder.
startButton_Click
, som anroparAccessTheWebAsync
och visar resultatet.AccessTheWebAsync
, som laddar ned innehållet på en webbplats som en sträng och returnerar längden på strängen.AccessTheWebAsync
använder en asynkron HttpClient metod, GetStringAsync(String), för att ladda ned innehållet.
Numrerade visningslinjer visas på strategiska punkter i hela programmet för att hjälpa dig att förstå hur programmet körs och för att förklara vad som händer vid varje punkt som markeras. Visningsraderna är märkta "ONE" till "SIX". Etiketterna representerar i vilken ordning programmet når dessa kodrader.
Följande kod visar en disposition av programmet.
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 &=
vbCrLf & $"Length of the downloaded string: {contentLength}." & vbCrLf
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://learn.microsoft.com")
' THREE
Dim urlContents As String = Await getStringTask
' FIVE
Return urlContents.Length
End Function
End Class
Var och en av de märkta platserna, "ONE" till "SIX", visar information om programmets aktuella tillstånd. Följande utdata genereras:
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.
Konfigurera programmet
Du kan ladda ned koden som det här avsnittet använder från MSDN, eller så kan du skapa den själv.
Kommentar
Om du vill köra exemplet måste du ha Visual Studio 2012 eller senare och .NET Framework 4.5 eller senare installerat på datorn.
Ladda ned programmet
Du kan ladda ned programmet för det här ämnet från Async Sample: Control Flow i Async-program. Följande steg öppnar och kör programmet.
Packa upp den nedladdade filen och starta sedan Visual Studio.
På menyraden väljer du Arkiv, Öppna, Projekt/Lösning.
Gå till mappen som innehåller den uppackade exempelkoden, öppna lösningen (.sln) och välj sedan F5-nyckeln för att skapa och köra projektet.
Skapa programmet själv
Följande WPF-projekt (Windows Presentation Foundation) innehåller kodexemplet för det här ämnet.
Utför följande steg för att köra projektet:
Starta Visual Studio.
På menyraden väljer du Arkiv, Nytt, Projekt.
Dialogrutan Nytt projekt öppnas.
I fönstret Installerade mallar väljer du Visual Basic och sedan WPF-program i listan över projekttyper.
Ange
AsyncTracer
som namnet på projektet och välj sedan ok-knappen .Det nya projektet visas i Solution Explorer.
I Visual Studio Code-redigeraren väljer du fliken MainWindow.xaml .
Om fliken inte visas öppnar du snabbmenyn för MainWindow.xaml i Solution Explorer och väljer sedan Visa kod.
I XAML-vyn i MainWindow.xaml ersätter du koden med följande kod.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://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>
Ett enkelt fönster som innehåller en textruta och en knapp visas i designvyn för MainWindow.xaml.
Lägg till en referens för System.Net.Http.
Öppna snabbmenyn för MainWindow.xaml.vb i Solution Explorer och välj sedan Visa kod.
I MainWindow.xaml.vb ersätter du koden med följande kod.
' 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://learn.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
Välj F5-tangenten för att köra programmet och välj sedan knappen Start .
Följande utdata bör visas:
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.
Spåra programmet
Steg ETT och TVÅ
De första två visningsraderna spårar sökvägen som startButton_Click
anrop AccessTheWebAsync
och AccessTheWebAsync
anropar den asynkrona HttpClient metoden GetStringAsync(String). Följande bild beskriver anropen från metod till metod.
Returtypen för båda AccessTheWebAsync
och client.GetStringAsync
är Task<TResult>. För AccessTheWebAsync
är TResult ett heltal. För GetStringAsync
är TResult en sträng. Mer information om returtyper för asynkron metod finns i Async Return Types (Visual Basic).
En aktivitetsreturerande asynkron metod returnerar en aktivitetsinstans när kontrollen flyttas tillbaka till anroparen. Kontrollen returnerar från en asynkron metod till anroparen antingen när en Await
operator påträffas i den anropade metoden eller när den anropade metoden slutar. De visningsrader som är märkta "THREE" till "SIX" spårar den här delen av processen.
Steg TRE
I AccessTheWebAsync
anropas den asynkrona metoden GetStringAsync(String) för att ladda ned innehållet på målwebbsidan. Kontrollen returnerar från client.GetStringAsync
till AccessTheWebAsync
när client.GetStringAsync
returneras.
Metoden client.GetStringAsync
returnerar en uppgift med strängen som har tilldelats variabeln getStringTask
i AccessTheWebAsync
. Följande rad i exempelprogrammet visar anropet till client.GetStringAsync
och tilldelningen.
Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com")
Du kan se uppgiften som ett löfte genom client.GetStringAsync
att skapa en verklig sträng så småningom. Under tiden, om AccessTheWebAsync
har arbete att göra som inte beror på den utlovade strängen från client.GetStringAsync
, kan det arbetet fortsätta medan client.GetStringAsync
väntar. I exemplet representerar följande rader med utdata, som är märkta "THREE", möjligheten att utföra oberoende arbete
THREE: Back in AccessTheWebAsync.
Task getStringTask is started.
About to await getStringTask & return a Task<int> to startButton_Click.
Följande instruktion pausar förloppet i AccessTheWebAsync
när getStringTask
inväntas.
Dim urlContents As String = Await getStringTask
Följande bild visar flödet av kontroll från client.GetStringAsync
till tilldelningen till getStringTask
och från skapandet av getStringTask
till programmet för en Await-operator.
Await-uttrycket pausas tills client.GetStringAsync
det returnerasAccessTheWebAsync
. Under tiden återgår kontrollen till anroparen för AccessTheWebAsync
, startButton_Click
.
Kommentar
Vanligtvis väntar du på anropet till en asynkron metod omedelbart. Följande tilldelning kan till exempel ersätta den tidigare koden som skapar och sedan väntar getStringTask
på : Dim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")
I det här avsnittet tillämpas inväntningsoperatorn senare för att hantera de utdatarader som markerar kontrollflödet genom programmet.
Steg FYRA
Den deklarerade returtypen AccessTheWebAsync
är Task(Of Integer)
. AccessTheWebAsync
När pausas returneras därför en aktivitet med heltal till startButton_Click
. Du bör förstå att den returnerade uppgiften inte getStringTask
är . Den returnerade aktiviteten är en ny uppgift med heltal som representerar vad som återstår att göra i den inaktiverade metoden . AccessTheWebAsync
Uppgiften är ett löfte från AccessTheWebAsync
för att skapa ett heltal när aktiviteten är klar.
Följande instruktion tilldelar den här aktiviteten till variabeln getLengthTask
.
Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()
Som i AccessTheWebAsync
kan startButton_Click
fortsätta med arbete som inte är beroende av resultatet av den asynkrona aktiviteten (getLengthTask
) tills aktiviteten väntar. Följande utdatarader representerar det arbetet:
FOUR: Back in startButton_Click.
Task getLengthTask is started.
About to await getLengthTask -- no caller to return to.
Förloppet i startButton_Click
pausas när getLengthTask
inväntas. Följande tilldelningsinstruktor pausas startButton_Click
tills AccessTheWebAsync
den är klar.
Dim contentLength As Integer = Await getLengthTask
I följande bild visar pilarna kontrollflödet från inväntningsuttrycket i AccessTheWebAsync
till tilldelningen av ett värde till getLengthTask
, följt av normal bearbetning i startButton_Click
tills getLengthTask
väntar.
Steg FEM
När client.GetStringAsync
signaler om att den är klar frisläpps bearbetningen från AccessTheWebAsync
avstängning och kan fortsätta förbi await-instruktionen. Följande rader med utdata representerar återupptagandet av bearbetningen:
FIVE: Back in AccessTheWebAsync.
Task getStringTask is complete.
Processing the return statement.
Exiting from AccessTheWebAsync.
Operand för retursatsen, urlContents.Length
, lagras i den uppgift som AccessTheWebAsync
returneras. Await-uttrycket hämtar det värdet från getLengthTask
i startButton_Click
.
Följande bild visar överföringen av kontrollen efter client.GetStringAsync
att (och getStringTask
) har slutförts.
AccessTheWebAsync
körs till slutförande och kontrollen återgår till startButton_Click
, som väntar på att slutföras.
Steg SEX
När AccessTheWebAsync
signaler om att den är klar kan bearbetningen fortsätta förbi await-instruktionen i startButton_Async
. Faktum är att programmet inte har något mer att göra.
Följande rader med utdata representerar återupptagandet av bearbetningen i startButton_Async
:
SIX: Back in startButton_Click.
Task getLengthTask is finished.
Result from AccessTheWebAsync is stored in contentLength.
About to display contentLength and exit.
Await-uttrycket hämtas från getLengthTask
heltalsvärdet som är operand för retursatsen i AccessTheWebAsync
. Följande instruktion tilldelar det värdet till variabeln contentLength
.
Dim contentLength As Integer = Await getLengthTask
Följande bild visar returen av kontrollen från AccessTheWebAsync
till startButton_Click
.