Share via


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

Notitie

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, waarmee het resultaat wordt aanroepen AccessTheWebAsync en weergegeven.

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

Notitie

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 worden geopend en uitgevoerd.

  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 ziet u een overzicht van de aanroepen van de methode naar de methode.

Steps ONE and TWO

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

Een asynchrone methode die een taak retourneert, retourneert een taakexemplaren wanneer het besturingselement 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. Het besturingselement keert terug van client.GetStringAsync naar AccessTheWebAsync wanneer client.GetStringAsync het retourneert.

De client.GetStringAsync methode retourneert een taak van een tekenreeks die is toegewezen aan de getStringTask variabele in AccessTheWebAsync. In de volgende regel in het voorbeeldprogramma ziet u 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 door client.GetStringAsync uiteindelijk een werkelijke tekenreeks te produceren. In de tussentijd, als AccessTheWebAsync er werk moet worden uitgevoerd dat niet afhankelijk is van de beloofde tekenreeks van client.GetStringAsync, kan dat werk worden voortgezet terwijl client.GetStringAsync er wordt gewacht. In het voorbeeld vertegenwoordigen de volgende uitvoerregels, die het label 'DRIE' hebben, de mogelijkheid om onafhankelijk werk uit te voeren

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 AccessTheWebAsync wanneer getStringTask wordt gewacht.

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 de toepassing van een Await-operator.

Step THREE

De wachtexpressie wordt opgeschort AccessTheWebAsync totdat client.GetStringAsync de expressie wordt geretourneerd. Ondertussen keert het besturingselement terug naar de beller van AccessTheWebAsync, startButton_Click.

Notitie

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

In dit onderwerp wordt de wachtoperator later toegepast om plaats te bieden aan de uitvoerregels die de controlestroom via het programma 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 het produceren van AccessTheWebAsync een geheel getal 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 in AccessTheWebAsync, startButton_Click kan doorgaan met werk dat niet afhankelijk is van de resultaten van de asynchrone taak (getLengthTask) totdat de taak wordt verwacht. De volgende uitvoerlijnen vertegenwoordigen dat werk:

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

startButton_Click De voortgang wordt opgeschort wanneer getLengthTask wordt gewacht. 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 de toewijzing van een waarde aan getLengthTask, gevolgd door de normale verwerking totdat startButton_ClickgetLengthTask wordt gewacht.

Step FOUR

Stap VIJF

Wanneer client.GetStringAsync de signalen zijn voltooid, wordt de verwerking AccessTheWebAsync vrijgegeven na de schorsing en kan deze verdergaan dan de await-instructie. De volgende uitvoerregels vertegenwoordigen de hervatting van de verwerking:

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

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

In de volgende afbeelding ziet u de overdracht van het besturingselement nadat client.GetStringAsync (en getStringTask) is voltooid.

Step FIVE

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

Stap ZES

Wanneer AccessTheWebAsync er signalen zijn dat het is voltooid, kan de verwerking verdergaan dan 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 wordt opgehaald uit getLengthTask de gehele waarde 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.

Step SIX

Zie ook