Partager via


Flux de contrôle dans les programmes asynchrones (Visual Basic)

Vous pouvez écrire et gérer des programmes asynchrones plus facilement à l’aide des mots clés et Await des Async mots clés. Toutefois, les résultats peuvent vous surprendre si vous ne comprenez pas le fonctionnement de votre programme. Cette rubrique trace le flux de contrôle via un programme asynchrone simple pour vous montrer quand le contrôle passe d’une méthode à une autre et quelles informations sont transférées chaque fois.

Remarque

Les Async mots clés et Await les mots clés ont été introduits dans Visual Studio 2012.

En général, vous marquez les méthodes qui contiennent du code asynchrone avec le modificateur asynchrone . Dans une méthode marquée avec un modificateur asynchrone, vous pouvez utiliser un opérateur Await (Visual Basic) pour spécifier où la méthode s’interrompt pour attendre la fin d’un processus asynchrone appelé. Pour plus d’informations, consultez Programmation asynchrone avec Async et Await (Visual Basic).

L’exemple suivant utilise des méthodes asynchrones pour télécharger le contenu d’un site web spécifié sous forme de chaîne et pour afficher la longueur de la chaîne. L’exemple contient les deux méthodes suivantes.

  • startButton_Click, qui appelle AccessTheWebAsync et affiche le résultat.

  • AccessTheWebAsync, qui télécharge le contenu d’un site web sous forme de chaîne et retourne la longueur de la chaîne. AccessTheWebAsync utilise une méthode asynchrone HttpClient , GetStringAsync(String)pour télécharger le contenu.

Les lignes d’affichage numérotées apparaissent à des points stratégiques tout au long du programme pour vous aider à comprendre comment le programme s’exécute et à expliquer ce qui se passe à chaque point marqué. Les lignes d’affichage sont étiquetées « ONE » à « SIX ». Les étiquettes représentent l’ordre dans lequel le programme atteint ces lignes de code.

Le code suivant présente un plan du programme.

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

Chacun des emplacements étiquetés, « ONE » à « SIX », affiche des informations sur l’état actuel du programme. La sortie suivante est produite :

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.

Configurer le programme

Vous pouvez télécharger le code que cette rubrique utilise à partir de MSDN, ou vous pouvez le générer vous-même.

Remarque

Pour exécuter l’exemple, vous devez disposer de Visual Studio 2012 ou version ultérieure et du .NET Framework 4.5 ou ultérieur installé sur votre ordinateur.

Télécharger le programme

Vous pouvez télécharger l’application pour cette rubrique à partir de l’exemple Async : Flux de contrôle dans les programmes asynchrones. Les étapes suivantes s’ouvrent et exécutent le programme.

  1. Décompressez le fichier téléchargé, puis démarrez Visual Studio.

  2. Dans la barre de menus, choisissez Fichier, Ouvrir, Projet/Solution.

  3. Accédez au dossier qui contient l’exemple de code décompressé, ouvrez le fichier de solution (.sln), puis choisissez la clé F5 pour générer et exécuter le projet.

Créer le programme vous-même

Le projet WPF (Windows Presentation Foundation) suivant contient l’exemple de code de cette rubrique.

Pour exécuter le projet, procédez comme suit :

  1. Démarrez Visual Studio.

  2. Dans le menu principal, sélectionnez Fichier, Nouveau, Projet.

    La boîte de dialogue Nouveau projet s’ouvre.

  3. Dans le volet Modèles installés , choisissez Visual Basic, puis choisissez Application WPF dans la liste des types de projets.

  4. Entrez AsyncTracer le nom du projet, puis choisissez le bouton OK .

    Le nouveau projet s’affiche dans l’Explorateur de solutions.

  5. Dans l'éditeur de code Visual Studio, choisissez l'onglet MainWindow.xaml .

    Si l’onglet n’est pas visible, ouvrez le menu contextuel de MainWindow.xaml dans l’Explorateur de solutions, puis choisissez Afficher le code.

  6. Dans la vue XAML de MainWindow.xaml, remplacez le code par le code suivant.

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

    Une fenêtre simple qui contient une zone de texte et un bouton s’affiche dans la vue Création de MainWindow.xaml.

  7. Ajoutez une référence pour System.Net.Http.

  8. Dans l’Explorateur de solutions, ouvrez le menu contextuel pour MainWindow.xaml.vb, puis choisissez Afficher le code.

  9. Dans MainWindow.xaml.vb, remplacez le code par le code suivant.

    ' 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. Appuyez sur la touche F5 pour exécuter le programme, puis choisissez le bouton Démarrer.

    La sortie suivante doit apparaître :

    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.
    

Suivre le programme

Étapes 1 et TWO

Les deux premières lignes d’affichage tracent le chemin en tant qu’appels startButton_ClickAccessTheWebAsyncet AccessTheWebAsync appellent la méthode GetStringAsync(String)asynchroneHttpClient. L’image suivante présente les appels de la méthode à la méthode.

Étapes ONE et TWO

Le type de retour des deux AccessTheWebAsync et client.GetStringAsync est Task<TResult>. Pour AccessTheWebAsync, TResult est un entier. Pour GetStringAsync, TResult est une chaîne. Pour plus d’informations sur les types de retour de méthode asynchrone, consultez Async Return Types (Visual Basic).

Une méthode asynchrone retournant une tâche retourne une instance de tâche lorsque le contrôle revient à l’appelant. Le contrôle retourne d’une méthode asynchrone à son appelant soit lorsqu’un Await opérateur est rencontré dans la méthode appelée, soit lorsque la méthode appelée se termine. Les lignes d’affichage étiquetées « THREE » à « SIX » tracent cette partie du processus.

Étape THREE

Dans AccessTheWebAsync, la méthode GetStringAsync(String) asynchrone est appelée pour télécharger le contenu de la page web cible. Le contrôle retourne à partir du client.GetStringAsync moment client.GetStringAsyncAccessTheWebAsync il est retourné.

La client.GetStringAsync méthode retourne une tâche de chaîne affectée à la getStringTask variable dans AccessTheWebAsync. La ligne suivante dans l’exemple de programme montre l’appel à client.GetStringAsync et l’affectation.

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

Vous pouvez considérer la tâche comme une promesse en produisant client.GetStringAsync éventuellement une chaîne réelle. En attendant, s’il AccessTheWebAsync y a du travail à faire, cela ne dépend pas de la chaîne promise à partir de client.GetStringAsynclaquelle , ce travail peut continuer pendant client.GetStringAsync les attentes. Dans l’exemple, les lignes de sortie suivantes, qui sont étiquetées « THREE », représentent l’opportunité d’effectuer un travail indépendant

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

L’instruction suivante interrompt la progression quand AccessTheWebAsyncgetStringTask elle est attendue.

Dim urlContents As String = Await getStringTask

L’image suivante montre le flux de contrôle de client.GetStringAsync l’affectation vers getStringTask et depuis la création de getStringTask l’application d’un opérateur Await.

Étape THREE

L’expression await s’interrompt AccessTheWebAsync jusqu’à ce qu’elle client.GetStringAsync retourne. En attendant, le contrôle retourne à l’appelant de AccessTheWebAsync, startButton_Click.

Remarque

En règle générale, vous attendez l’appel à une méthode asynchrone immédiatement. Par exemple, l’affectation suivante peut remplacer le code précédent qui crée, puis attend :getStringTaskDim urlContents As String = Await client.GetStringAsync("https://learn.microsoft.com")

Dans cette rubrique, l’opérateur await est appliqué ultérieurement pour prendre en charge les lignes de sortie qui marquent le flux de contrôle via le programme.

Étape QUATRE

Le type de AccessTheWebAsync retour déclaré est Task(Of Integer). Par conséquent, lorsqu’elle AccessTheWebAsync est suspendue, elle retourne une tâche d’entier à startButton_Click. Vous devez comprendre que la tâche retournée n’est pas getStringTask. La tâche retournée est une nouvelle tâche d’entier qui représente ce qui reste à faire dans la méthode suspendue. AccessTheWebAsync La tâche est une promesse de AccessTheWebAsync produire un entier lorsque la tâche est terminée.

L’instruction suivante affecte cette tâche à la getLengthTask variable.

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

Comme dans AccessTheWebAsyncle cas contraire, startButton_Click peut continuer avec le travail qui ne dépend pas des résultats de la tâche asynchrone (getLengthTask) tant que la tâche n’est pas attendue. Les lignes de sortie suivantes représentent ce travail :

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

La progression est startButton_Click suspendue quand getLengthTask elle est attendue. L’instruction d’affectation suivante s’interrompt startButton_Click jusqu’à ce qu’elle AccessTheWebAsync soit terminée.

Dim contentLength As Integer = Await getLengthTask

Dans l’illustration suivante, les flèches montrent le flux de contrôle de l’expression await dans AccessTheWebAsync l’affectation d’une valeur à getLengthTask, suivi du traitement normal jusqu’à startButton_Click ce qu’il getLengthTask soit attendu.

Étape QUATRE

Étape CINQ

Lorsque client.GetStringAsync les signaux indiquent qu’il est terminé, le traitement AccessTheWebAsync est libéré de la suspension et peut continuer après l’instruction Await. Les lignes de sortie suivantes représentent la reprise du traitement :

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

L’opérande de l’instruction return, est urlContents.Lengthstocké dans la tâche qui AccessTheWebAsync retourne. L’expression await récupère cette valeur dans getLengthTaskstartButton_Click.

L’image suivante montre le transfert du contrôle après client.GetStringAsync (et getStringTask) terminé.

Étape FIVE

AccessTheWebAsync s’exécute à l’achèvement, et le contrôle retourne à startButton_Click, ce qui est en attente de l’achèvement.

Étape SIX

Lorsque AccessTheWebAsync les signaux qu’il est terminé, le traitement peut continuer après l’instruction await en startButton_Async. En fait, le programme n’a rien de plus à faire.

Les lignes de sortie suivantes représentent la reprise du traitement dans startButton_Async:

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

L’expression await récupère à partir de getLengthTask la valeur entière qui est l’opérande de l’instruction return dans AccessTheWebAsync. L’instruction suivante affecte cette valeur à la contentLength variable.

Dim contentLength As Integer = Await getLengthTask

L’image suivante montre le retour du contrôle à startButton_Clickpartir de AccessTheWebAsync .

Étape SIX

Voir aussi