Delen via


Besturingsstroom in Async-programma's (Visual Basic)

U kunt asynchrone programma's eenvoudiger schrijven en onderhouden met behulp van de Async en Await trefwoorden. De resultaten kunnen u echter verrassen als u niet begrijpt hoe uw programma werkt. Dit onderwerp traceert de controlestroom via een eenvoudig asynchroon programma om u te laten zien wanneer het besturingselement van de ene methode naar de andere wordt verplaatst en welke informatie telkens wordt overgedragen.

Opmerking

De Async trefwoorden en Await trefwoorden zijn geïntroduceerd in Visual Studio 2012.

Over het algemeen markeert u methoden die asynchrone code bevatten met de Asynchrone wijziging. In een methode die is gemarkeerd met een asynchrone wijziging, kunt u een Operator Await (Visual Basic) gebruiken om op te geven waar de methode wordt onderbroken om te wachten tot een aangeroepen asynchroon proces is voltooid. Zie Asynchroon programmeren met Async en Await (Visual Basic) voor meer informatie.

In het volgende voorbeeld worden asynchrone methoden gebruikt om de inhoud van een opgegeven website als tekenreeks te downloaden en de lengte van de tekenreeks weer te geven. Het voorbeeld bevat de volgende twee methoden.

  • startButton_Click, die AccessTheWebAsync oproept en het resultaat weergeeft.

  • AccessTheWebAsync, waarmee de inhoud van een website als tekenreeks wordt gedownload en de lengte van de tekenreeks wordt geretourneerd. AccessTheWebAsync gebruikt een asynchrone HttpClient methode GetStringAsync(String)om de inhoud te downloaden.

Genummerde weergavelijnen worden weergegeven op strategische punten in het programma om u te helpen begrijpen hoe het programma wordt uitgevoerd en om uit te leggen wat er gebeurt op elk punt dat is gemarkeerd. De weergavelijnen hebben het label 'ONE' tot en met 'SIX'. De labels vertegenwoordigen de volgorde waarin het programma deze coderegels bereikt.

De volgende code toont een overzicht van het programma.

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

Elk van de gelabelde locaties, 'ONE' tot en met 'ZES', geeft informatie weer over de huidige status van het programma. De volgende uitvoer wordt geproduceerd:

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.

Het programma instellen

U kunt de code downloaden die in dit onderwerp wordt gebruikt vanuit MSDN, of u kunt deze zelf bouwen.

Opmerking

Als u het voorbeeld wilt uitvoeren, moet Visual Studio 2012 of hoger en .NET Framework 4.5 of hoger op uw computer zijn geïnstalleerd.

Het programma downloaden

U kunt de toepassing voor dit onderwerp downloaden uit Async Sample: Control Flow in Async Programs. De volgende stappen openen en starten het programma.

  1. Pak het gedownloade bestand uit en start Visual Studio.

  2. Kies Bestand, Openen, Project/Oplossing in de menubalk.

  3. Navigeer naar de map met de uitgepakte voorbeeldcode, open het oplossingsbestand (.sln) en kies vervolgens de F5-sleutel om het project te bouwen en uit te voeren.

Zelf het programma bouwen

Het volgende WpF-project (Windows Presentation Foundation) bevat het codevoorbeeld voor dit onderwerp.

Voer de volgende stappen uit om het project uit te voeren:

  1. Start Visual Studio.

  2. Kies Bestand, Nieuw, Project in de menubalk.

    Het dialoogvenster Nieuw project wordt geopend.

  3. Kies Visual Basic in het deelvenster Geïnstalleerde sjablonen en kies vervolgens WPF-toepassing in de lijst met projecttypen.

  4. Voer AsyncTracer de naam van het project in en kies vervolgens de knop OK .

    Het nieuwe project wordt weergegeven in Solution Explorer.

  5. Kies in de Visual Studio Code-editor het tabblad MainWindow.xaml .

    Als het tabblad niet zichtbaar is, opent u het snelmenu voor MainWindow.xaml in Solution Explorer en kiest u Code weergeven.

  6. Vervang in de XAML-weergave van MainWindow.xaml de code door de volgende code.

    <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>
    

    Een eenvoudig venster met een tekstvak en een knop wordt weergegeven in de ontwerpweergave van MainWindow.xaml.

  7. Voeg een verwijzing toe voor System.Net.Http.

  8. Open in Solution Explorer het snelmenu voor MainWindow.xaml.vb en kies Code weergeven.

  9. Vervang in MainWindow.xaml.vb de code door de volgende 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://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
    
  10. Kies de F5-toets om het programma uit te voeren en kies vervolgens de knop Start .

    De volgende uitvoer moet worden weergegeven:

    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.
    

Het programma traceren

Stap ÉÉN en TWEE

De eerste twee weergavelijnen traceren het pad als startButton_Click aanroepen AccessTheWebAsyncen AccessTheWebAsync roepen de asynchrone HttpClient methode GetStringAsync(String)aan. In de volgende afbeelding wordt een overzicht getoond van de oproepen tussen methoden.

Stappen EEN en TWEE

Het retourtype van beide AccessTheWebAsync en client.GetStringAsync is Task<TResult>. Voor AccessTheWebAsync, is TResult een geheel getal. Voor GetStringAsync is TResult een tekenreeks. Zie Asynchrone retourtypen (Visual Basic) voor meer informatie over retourtypen van asynchrone methoden.

Een asynchrone methode die een taak retourneert, retourneert een taakexemplaar wanneer de controle wordt teruggezet naar de aanroeper. Het besturingselement retourneert van een asynchrone methode naar de aanroeper wanneer een Await operator wordt aangetroffen in de aangeroepen methode of wanneer de aangeroepen methode eindigt. De weergavelijnen met het label 'DRIE' tot en met 'SIX' traceren dit deel van het proces.

Stap DRIE

In AccessTheWebAsyncwordt de asynchrone methode GetStringAsync(String) aangeroepen om de inhoud van de doelwebpagina te downloaden. De controle keert terug van client.GetStringAsync naar AccessTheWebAsync wanneer client.GetStringAsync terugkeert.

De client.GetStringAsync methode retourneert een taak van een tekenreeks die is toegewezen aan de getStringTask variabele in AccessTheWebAsync. De volgende regel in het voorbeeldprogramma toont de aanroep van client.GetStringAsync en de toewijzing.

Dim getStringTask As Task(Of String) = client.GetStringAsync("https://learn.microsoft.com")

U kunt de taak zien als een belofte van client.GetStringAsync om uiteindelijk een daadwerkelijke tekenreeks te produceren. In de tussentijd, als AccessTheWebAsync werk moet doen dat niet afhankelijk is van de beloofde tekenreeks van client.GetStringAsync, kan dat werk worden voortgezet, terwijl er op client.GetStringAsync wordt gewacht. In het voorbeeld vertegenwoordigen de volgende outputregels, die het label 'DRIE' hebben, de mogelijkheid om onafhankelijk werk te doen.

THREE: Back in AccessTheWebAsync.
           Task getStringTask is started.
           About to await getStringTask & return a Task<int> to startButton_Click.

De volgende instructie onderbreekt de voortgang in AccessTheWebAsync wanneer er wordt gewacht op getStringTask.

Dim urlContents As String = Await getStringTask

In de volgende afbeelding ziet u de controlestroom van client.GetStringAsync naar de toewijzing van getStringTask en van het maken van getStringTask naar de toepassing van een Await-operator.

Stap DRIE

De wachtexpressie pauzeert AccessTheWebAsync totdat client.GetStringAsync een resultaat teruggeeft. Ondertussen gaat de controle terug naar degene die heeft opgeroepen AccessTheWebAsync, startButton_Click.

Opmerking

Normaal gesproken wacht u onmiddellijk op de aanroep van een asynchrone methode. De volgende toewijzing kan bijvoorbeeld de vorige code vervangen die getStringTask creëert en erop wacht: Dim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")

In dit onderwerp wordt de await-operator later toegepast om ruimte te maken voor de uitvoerlijnen die de controlestroom door het programma heen markeren.

Stap VIER

Het gedeclareerde retourtype AccessTheWebAsync is Task(Of Integer). Daarom, wanneer AccessTheWebAsync wordt onderbroken, retourneert het een taak van geheel getal naar startButton_Click. U moet begrijpen dat de geretourneerde taak niet getStringTaskis. De geretourneerde taak is een nieuwe taak van een geheel getal dat aangeeft wat er nog moet worden gedaan in de onderbroken methode, AccessTheWebAsync. De taak is een belofte van AccessTheWebAsync om een geheel getal te produceren wanneer de taak is voltooid.

Met de volgende instructie wordt deze taak toegewezen aan de getLengthTask variabele.

Dim getLengthTask As Task(Of Integer) = AccessTheWebAsync()

Zoals bij AccessTheWebAsync, kan startButton_Click doorgaan met werk dat niet afhankelijk is van de resultaten van de asynchrone taak (getLengthTask) totdat er op de taak wordt gewacht. De volgende uitvoerlijnen vertegenwoordigen dat werk:

FOUR:  Back in startButton_Click.
           Task getLengthTask is started.
           About to await getLengthTask -- no caller to return to.

De voortgang van startButton_Click wordt opgeschort wanneer op getLengthTask gewacht wordt. De volgende toewijzingsinstructie startButton_Click wordt opgeschort totdat AccessTheWebAsync deze is voltooid.

Dim contentLength As Integer = Await getLengthTask

In de volgende afbeelding tonen de pijlen de controlestroom van de wachtexpressie in AccessTheWebAsync tot de toewijzing van een waarde aan getLengthTask, gevolgd door de normale verwerking in startButton_Click totdat er bij getLengthTask moet worden gewacht.

Stap VIER

Stap 5

Wanneer client.GetStringAsync aangeeft dat het is voltooid, wordt de verwerking in AccessTheWebAsync hervat na de opschorting en kan verdergaan na de await-instructie. De volgende uitvoerregels geven de hervatting van de verwerking weer.

FIVE:  Back in AccessTheWebAsync.
           Task getStringTask is complete.
           Processing the return statement.
           Exiting from AccessTheWebAsync.

De operand van de retourinstructie, urlContents.Length, wordt opgeslagen in de taak die door AccessTheWebAsync wordt geretourneerd. De await-expressie haalt die waarde op uit getLengthTask in startButton_Click.

Op de volgende afbeelding ziet u de overdracht van de controle nadat client.GetStringAsync (en getStringTask) zijn voltooid.

Stap VIJF

AccessTheWebAsync wordt uitgevoerd tot voltooiing en het besturingselement keert terug naar startButton_Click, dat wacht op de voltooiing.

Stap ZES

Wanneer AccessTheWebAsync signaleert dat het is voltooid, kan de verwerking doorgaan na de await-instructie in startButton_Async. In feite heeft het programma niets meer te doen.

De volgende uitvoerregels vertegenwoordigen de hervatting van de verwerking in startButton_Async:

SIX:   Back in startButton_Click.
           Task getLengthTask is finished.
           Result from AccessTheWebAsync is stored in contentLength.
           About to display contentLength and exit.

De await-expressie haalt uit getLengthTask de integer waarde op die de operand is van de retourinstructie in AccessTheWebAsync. Met de volgende instructie wordt die waarde toegewezen aan de contentLength variabele.

Dim contentLength As Integer = Await getLengthTask

In de volgende afbeelding ziet u de terugkeer van het besturingselement van AccessTheWebAsync naar startButton_Click.

Stap ZES

Zie ook