Partager via


Gestion de la réentrance dans Async Apps (C# et Visual Basic)

Lorsque vous incluez le code asynchrone dans votre application, vous devez prendre en compte et éventuellement empêcher la réentrance, qui fait référence à entrer une opération asynchrone avant son exécution.Si vous ne reconnaissez pas et ne gérez pas de risques pour la réentrance, il peut provoquer des résultats inattendus.

Dans cette rubrique

[!REMARQUE]

Les instructions dans Examen et exécuter l'exemple Applications vous montrent comment exécuter le code comme une application Windows Presentation Foundation (WPF) ou comme les fenêtres signalent l'application.

Pour exécuter l'exemple comme une application WPF, vous devez avoir installé Visual Studio 2012 Visual Studio express 2012 pour le bureau Windows, ou .NET Framework 4,5 sur votre ordinateur.

Pour exécuter l'exemple comme une application à Windows Store, vous devez avoir windows 8 installées sur votre ordinateur.En outre, si vous souhaitez exécuter l'exemple Visual Studio, vous devez également avoir Visual Studio 2012 ou Visual Studio express 2012 pour windows 8 installé.

ID de Réentrance

Dans l'exemple de cette rubrique, les utilisateurs choisissent un bouton Démarrer pour initialiser une application asynchrone qui télécharge une série de sites Web et calcule le nombre total d'octets qui sont téléchargés.Une version synchrone de l'exemple répondrait la même façon indépendamment du nombre de fois où un utilisateur choisit le bouton pour, après la première fois, le thread d'interface utilisateur ignore événements jusqu'à ce que l'application finisse d'exécuter.Dans une application asynchrone, toutefois, le thread d'interface utilisateur continue de répondre, et vous pouvez entrer à nouveau l'opération asynchrone avant qu'elle soit terminée.

L'exemple suivant illustre la sortie attendue si l'utilisateur choisit le bouton Démarrer une seule fois.Une liste des sites Web téléchargés apparaît avec la taille, en octets, de chaque site.Total d'octets apparaît à la fin.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
7. msdn.microsoft.com                                            42972
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

Toutefois, si l'utilisateur choisit le bouton plusieurs fois, le gestionnaire d'événements est appelé à plusieurs reprises, et l'opération de téléchargement est ressaisie chaque fois.Par conséquent, plusieurs opérations asynchrones s'exécutent en même temps, les feuillets intercalés de sortie les résultats, et le nombre total d'octets est confusion.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
7. msdn.microsoft.com                                            42972
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
7. msdn.microsoft.com                                            42972
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
7. msdn.microsoft.com                                            42972
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

Vous pouvez examiner le code qui génère cette sortie en faisant défiler à la fin de cette rubrique.Vous pouvez essayer le code en téléchargeant la solution sur votre ordinateur local puis exécute le projet de WebsiteDownload ou en utilisant du code à la fin de cette rubrique pour créer votre propre projet pour plus d'informations et des instructions, consultez Examen et exécuter l'exemple Applications.

Gestion Réentrance

Vous pouvez gérer la réentrance de diverses façons, selon ce que votre application à effectuer.Cette rubrique répertorie les exemples suivants :

JJ651641.collapse_all(fr-fr,VS.110).gifDésactivez le bouton amorçage

Vous pouvez bloquer le bouton Démarrer pendant qu'une opération s'exécute en désactivant le bouton en haut du gestionnaire d'événements d' StartButton_Click .Vous pouvez ensuite permettre à nouveau sur le bouton d'un bloc d' finally lorsque l'opération se termine afin que les utilisateurs puissent exécuter l'application.

Le code suivant illustre ces modifications, qui sont marquées avec des astérisques.Vous pouvez ajouter des modifications au code à la fin de cette rubrique, ou vous pouvez télécharger l'application finie de Exemples Async : Réentrance dans les applications de Bureau .NET ou Exemples Async : Réentrance dans les applications de mémoire windows.Le nom du projet est DisableStartButton.

Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
    ' This line is commented out to make the results clearer in the output.
    'ResultsTextBox.Text = ""

    ' ***Disable the Start button until the downloads are complete. 
    StartButton.IsEnabled = False

    Try
        Await AccessTheWebAsync()

    Catch ex As Exception
        ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    ' ***Enable the Start button in case you want to run the program again. 
    Finally
        StartButton.IsEnabled = True

    End Try
End Sub
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // This line is commented out to make the results clearer in the output.
    //ResultsTextBox.Text = "";

    // ***Disable the Start button until the downloads are complete. 
    StartButton.IsEnabled = false; 

    try
    {
        await AccessTheWebAsync();
    }
    catch (Exception)
    {
        ResultsTextBox.Text += "\r\nDownloads failed.";
    }
    // ***Enable the Start button in case you want to run the program again. 
    finally
    {
        StartButton.IsEnabled = true;
    }
}

À la suite de modifications, le bouton ne répond pas pendant qu' AccessTheWebAsync télécharge les sites Web, le processus ne peut pas être ressaisi.

JJ651641.collapse_all(fr-fr,VS.110).gifSupprimez et redémarrez l'exécution

Au lieu de désactiver le bouton Démarrer, vous pouvez stocker le bouton actif, mais si l'utilisateur choisit ce bouton de nouveau, annulez l'opération qui s'exécute déjà et permet l'exécution récemment démarrée continuer.

Pour plus d'informations sur l'annulation, consultez l' Affiner votre application Async.

Pour configurer ce cas, apportez les modifications suivantes au code de base qui est fourni dans Examen et exécuter l'exemple Applications.Vous pouvez également télécharger l'application finie de Exemples Async : Réentrance dans les applications de Bureau .NET ou Exemples Async : Réentrance dans les applications de mémoire windows.Le nom de ce projet est CancelAndRestart.

  1. Déclarez une variable d' CancellationTokenSource, cts, qui est dans la portée de toutes les méthodes.

    Class MainWindow // Or Class MainPage
    
        ' *** Declare a System.Threading.CancellationTokenSource.
        Dim cts As CancellationTokenSource
    
    public partial class MainWindow : Window   // Or class MainPage
    {
        // *** Declare a System.Threading.CancellationTokenSource.
        CancellationTokenSource cts;
    
  2. Dans StartButton_Click, déterminez si une opération est en cours.Si la valeur d' cts est null (Nothing en Visual Basic), aucune opération n'est déjà actif.Si la valeur n'est pas nul, l'opération en cours de exécution est annulée.

    ' *** If a download process is already underway, cancel it.
    If cts IsNot Nothing Then
        cts.Cancel()
    End If
    
    // *** If a download process is already underway, cancel it.
    if (cts != null)
    {
        cts.Cancel();
    }
    
  3. Définissez cts une valeur différente qui représente le processus actuel.

    ' *** Now set cts to cancel the current process if the button is chosen again.
    Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
    cts = newCTS
    
    // *** Now set cts to a new value that you can use to cancel the current process
    // if the button is chosen again.
    CancellationTokenSource newCTS = new CancellationTokenSource();
    cts = newCTS;
    
  4. À la fin de StartButton_Click, le processus actuel est terminé, donc définir la valeur d' cts vers null.

    ' *** When the process completes, signal that another process can proceed.
    If cts Is newCTS Then
        cts = Nothing
    End If
    
    // *** When the process is complete, signal that another process can begin.
    if (cts == newCTS)
        cts = null;
    

Le code suivant montre toutes les modifications dans StartButton_Click.Les ajouts sont marqués avec des astérisques.

Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)

    ' This line is commented out to make the results clearer. 
    'ResultsTextBox.Text = ""


    ' *** If a download process is underway, cancel it.
    If cts IsNot Nothing Then
        cts.Cancel()
    End If

    ' *** Now set cts to cancel the current process if the button is chosen again.
    Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
    cts = newCTS

    Try
        ' *** Send a token to carry the message if the operation is canceled.
        Await AccessTheWebAsync(cts.Token)
        

    Catch ex As OperationCanceledException
        ResultsTextBox.Text &= vbCrLf & "Download canceled." & vbCrLf

    Catch ex As Exception
        ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    End Try

    ' *** When the process is complete, signal that another process can proceed.
    If cts Is newCTS Then
        cts = Nothing
    End If
End Sub
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // This line is commented out to make the results clearer in the output.
    //ResultsTextBox.Clear();

    // *** If a download process is already underway, cancel it.
    if (cts != null)
    {
        cts.Cancel();
    }

    // *** Now set cts to cancel the current process if the button is chosen again.
    CancellationTokenSource newCTS = new CancellationTokenSource();
    cts = newCTS;

    try
    {
        // ***Send cts.Token to carry the message if there is a cancellation request.
        await AccessTheWebAsync(cts.Token);
        
    }
    // *** Catch cancellations separately.
    catch (OperationCanceledException)
    {
        ResultsTextBox.Text += "\r\nDownloads canceled.\r\n";
    }
    catch (Exception)
    {
        ResultsTextBox.Text += "\r\nDownloads failed.\r\n";
    }
    // *** When the process is complete, signal that another process can proceed.
    if (cts == newCTS)
        cts = null;
}

Dans AccessTheWebAsync, apportez les modifications suivantes.

  • Ajoutez un paramètre pour accepter le jeton d'annulation d' StartButton_Click.

  • Utilisez la méthode d' GetAsync pour télécharger les sites Web parce qu' GetAsync accepte un argument d' CancellationToken .

  • Avant d'appeler DisplayResults pour afficher les résultats pour chaque site Web téléchargé, contrôle ct pour vérifier que l'opération en cours n'a pas été annulée.

Le code suivant illustre ces modifications, qui sont marquées avec des astérisques.

' *** Provide a parameter for the CancellationToken from StartButton_Click.
Private Async Function AccessTheWebAsync(ct As CancellationToken) As Task

    ' Declare an HttpClient object.
    Dim client = New HttpClient()

    ' Make a list of web addresses.
    Dim urlList As List(Of String) = SetUpURLList()

    Dim total = 0
    Dim position = 0

    For Each url In urlList
        ' *** Use the HttpClient.GetAsync method because it accepts a 
        ' cancellation token.
        Dim response As HttpResponseMessage = Await client.GetAsync(url, ct)

        ' *** Retrieve the website contents from the HttpResponseMessage.
        Dim urlContents As Byte() = Await response.Content.ReadAsByteArrayAsync()

        ' *** Check for cancellations before displaying information about the 
        ' latest site. 
        ct.ThrowIfCancellationRequested()

        position += 1
        DisplayResults(url, urlContents, position)

        ' Update the total.
        total += urlContents.Length
    Next

    ' Display the total count for all of the websites.
    ResultsTextBox.Text &=
        String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned:  " & total & vbCrLf)
End Function
// *** Provide a parameter for the CancellationToken from StartButton_Click.
async Task AccessTheWebAsync(CancellationToken ct)
{
    // Declare an HttpClient object.
    HttpClient client = new HttpClient();

    // Make a list of web addresses.
    List<string> urlList = SetUpURLList();

    var total = 0;
    var position = 0;

    foreach (var url in urlList)
    {
        // *** Use the HttpClient.GetAsync method because it accepts a 
        // cancellation token.
        HttpResponseMessage response = await client.GetAsync(url, ct);

        // *** Retrieve the website contents from the HttpResponseMessage.
        byte[] urlContents = await response.Content.ReadAsByteArrayAsync();

        // *** Check for cancellations before displaying information about the 
        // latest site. 
        ct.ThrowIfCancellationRequested();

        DisplayResults(url, urlContents, ++position);

        // Update the total.
        total += urlContents.Length;
    }

    // Display the total count for all of the websites.
    ResultsTextBox.Text +=
        string.Format("\r\n\r\nTOTAL bytes returned:  {0}\r\n", total);
}   

Si vous choisissez le bouton Démarrer plusieurs fois pendant que l'application s'exécute, elle doit produire des résultats qui ressemble à la sortie suivante.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               122505
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
Download canceled.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
Download canceled.

1. msdn.microsoft.com/en-us/library/hh191443.aspx                83732
2. msdn.microsoft.com/en-us/library/aa578028.aspx               205273
3. msdn.microsoft.com/en-us/library/jj155761.aspx                29019
4. msdn.microsoft.com/en-us/library/hh290140.aspx               117152
5. msdn.microsoft.com/en-us/library/hh524395.aspx                68959
6. msdn.microsoft.com/en-us/library/ms404677.aspx               197325
7. msdn.microsoft.com                                            42972
8. msdn.microsoft.com/en-us/library/ff730837.aspx               146159

TOTAL bytes returned:  890591

Pour supprimer les listes partielles, supprimez les marques de commentaire de la première ligne de code dans StartButton_Click pour effacer la zone de texte à chaque fois que l'utilisateur redémarre l'exécution.

JJ651641.collapse_all(fr-fr,VS.110).gifExécuter plusieurs opérations et mettez en file d'attente la sortie

Troisième cet exemple est plus complexe car l'application démarre une autre opération asynchrone chaque fois que l'utilisateur choisit le bouton Démarrer, et toutes les opérations exécutées à l'achèvement.Toutes les opérations demandées téléchargent les sites Web de la liste de façon asynchrone, mais la sortie des opérations est présentée séquentiellement.Autrement dit, l'activité réelle de téléchargement est entrelacée, comme la sortie dans ID de Réentrance affiche, mais la liste de résultats pour chaque groupe est présentée séparément.

Les opérations partagent Taskglobal, pendingWork, qui sert de garde-porte au processus d'affichage.

Vous pouvez exécuter cet exemple en collant les modifications dans le code de Génération d'Applications, ou vous pouvez suivre les instructions dans Télécharger Applications de télécharger l'exemple puis de gérer le projet de QueueResults.

La sortie suivante montre le résultat si l'utilisateur choisit le bouton Démarrer une seule fois.L'étiquette de lettre, Un, indique que le résultat est la première fois du bouton Démarrer est sélectionnez.Les nombres indiquent l'ordre des URL dans la liste de cibles de téléchargement.

#Starting group A.
#Task assigned for group A.

A-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
A-2. msdn.microsoft.com/en-us/library/aa578028.aspx               209858
A-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
A-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
A-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
A-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
A-7. msdn.microsoft.com                                            53266
A-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148020

TOTAL bytes returned:  918876


#Group A is complete.

Si l'utilisateur choisit le bouton Démarrer trois fois, l'application génère la sortie semblable aux lignes suivantes.Les lignes d'information qui commencent par une trace de signe dièse (#) la progression de l'application.

#Starting group A.
#Task assigned for group A.

A-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
A-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
A-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
A-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
A-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71259
A-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199185

#Starting group B.
#Task assigned for group B.

A-7. msdn.microsoft.com                                            53266

#Starting group C.
#Task assigned for group C.

A-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010

TOTAL bytes returned:  916095

B-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
B-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
B-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
B-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
B-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
B-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186

#Group A is complete.

B-7. msdn.microsoft.com                                            53266
B-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010

TOTAL bytes returned:  916097

C-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
C-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089

#Group B is complete.

C-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
C-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
C-5. msdn.microsoft.com/en-us/library/hh524395.aspx                72765
C-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
C-7. msdn.microsoft.com                                            56190
C-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010

TOTAL bytes returned:  920526

#Group C is complete.

Les groupes B et C démarrent avant que le groupe A terminé, mais la sortie pour chaque groupe apparaît séparément.Toute la sortie pour le groupe apparaît en premier, suivi de l'ensemble de la sortie de B de groupe, puis de toutes les sorties de C de groupe.L'application affiche toujours les groupes dans l'ordre et, pour chaque groupe, affiche toujours les informations sur les différents sites Web dans l'ordre qui les URL qui apparaissent dans la liste d'URL.

Toutefois, vous ne pouvez pas prédire l'ordre dans lequel les téléchargements se produisent réellement.Après plusieurs groupes ont été démarré, toutes les tâches de téléchargement qu'ils génèrent sont actives.Vous ne pouvez pas supposer qu'A-1 sera téléchargé avant B-1, et vous ne pouvez pas supposer qu'A-1 sera téléchargé avant A-2.

JJ651641.collapse_all(fr-fr,VS.110).gifDéfinitions globales

L'exemple de code contient les deux déclarations globales suivantes qui sont visibles de toutes les méthodes.

Class MainWindow    ' Class MainPage in Windows Store app.

    ' ***Declare the following variables where all methods can access them. 
    Private pendingWork As Task = Nothing
    Private group As Char = ChrW(AscW("A") - 1)
public partial class MainWindow : Window  // Class MainPage in Windows Store app.
{
    // ***Declare the following variables where all methods can access them. 
    private Task pendingWork = null;   
    private char group = (char)('A' - 1);

La variable d' Task, pendingWork, surveille le processus d'affichage et empêché tout groupe d'interrompre l'exécution de l'affichage d'un autre groupe.La variable de caractère, groupétiquette, la sortie de différents groupes pour vérifier que les résultats s'affichent dans l'ordre attendu.

JJ651641.collapse_all(fr-fr,VS.110).gifLe gestionnaire d'événements clic

Le gestionnaire d'événements, StartButton_Click, index la lettre du groupe chaque fois que l'utilisateur choisit le bouton Démarrer .Le gestionnaire appelle AccessTheWebAsync pour exécuter l'opération de téléchargement.

Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
    ' ***Verify that each group's results are displayed together, and that
    ' the groups display in order, by marking each group with a letter.
    group = ChrW(AscW(group) + 1)
    ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Starting group {0}.", group)

    Try
        ' *** Pass the group value to AccessTheWebAsync.
        Dim finishedGroup As Char = Await AccessTheWebAsync(group)

        ' The following line verifies a successful return from the download and 
        ' display procedures. 
        ResultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "#Group {0} is complete." & vbCrLf, finishedGroup)

    Catch ex As Exception
        ResultsTextBox.Text &= vbCrLf & "Downloads failed."

    End Try
End Sub
private async void StartButton_Click(object sender, RoutedEventArgs e)
{
    // ***Verify that each group's results are displayed together, and that
    // the groups display in order, by marking each group with a letter.
    group = (char)(group + 1);
    ResultsTextBox.Text += string.Format("\r\n\r\n#Starting group {0}.", group);

    try
    {
        // *** Pass the group value to AccessTheWebAsync.
        char finishedGroup = await AccessTheWebAsync(group);

        // The following line verifies a successful return from the download and
        // display procedures. 
        ResultsTextBox.Text += string.Format("\r\n\r\n#Group {0} is complete.\r\n", finishedGroup);
    }
    catch (Exception)
    {
        ResultsTextBox.Text += "\r\nDownloads failed.";
    }
}

JJ651641.collapse_all(fr-fr,VS.110).gifLa méthode d'AccessTheWebAsync

Cet exemple couper AccessTheWebAsync en deux méthodes.La première méthode, AccessTheWebAsync, le lance toutes les tâches de téléchargement d'un groupe et configure pendingWork pour contrôler le processus d'affichage.La méthode utilise (langage Integrated Query requête LINQ) et ToArray<TSource> pour démarrer toutes les tâches de téléchargement en même temps.

AccessTheWebAsync appelle ensuite FinishOneGroupAsync pour attendre la fin de chaque téléchargement et afficher sa longueur.

FinishOneGroupAsync retourne une tâche assignée à pendingWork dans AccessTheWebAsync.Que la valeur empêché l'interruption par une autre opération avant que la tâche terminée.

Private Async Function AccessTheWebAsync(grp As Char) As Task(Of Char)

    Dim client = New HttpClient()

    ' Make a list of the web addresses to download.
    Dim urlList As List(Of String) = SetUpURLList()

    ' ***Kick off the downloads. The application of ToArray activates all the download tasks.
    Dim getContentTasks As Task(Of Byte())() =
        urlList.Select(Function(addr) client.GetByteArrayAsync(addr)).ToArray()

    ' ***Call the method that awaits the downloads and displays the results.
    ' Assign the Task that FinishOneGroupAsync returns to the gatekeeper task, pendingWork.
    pendingWork = FinishOneGroupAsync(urlList, getContentTasks, grp)

    ResultsTextBox.Text &=
        String.Format(vbCrLf & "#Task assigned for group {0}. Download tasks are active." & vbCrLf, grp)

    ' ***This task is complete when a group has finished downloading and displaying.
    Await pendingWork

    ' You can do other work here or just return.
    Return grp
End Function
private async Task<char> AccessTheWebAsync(char grp)
{
    HttpClient client = new HttpClient();

    // Make a list of the web addresses to download.
    List<string> urlList = SetUpURLList();

    // ***Kick off the downloads. The application of ToArray activates all the download tasks.
    Task<byte[]>[] getContentTasks = urlList.Select(url => client.GetByteArrayAsync(url)).ToArray();

    // ***Call the method that awaits the downloads and displays the results.
    // Assign the Task that FinishOneGroupAsync returns to the gatekeeper task, pendingWork.
    pendingWork = FinishOneGroupAsync(urlList, getContentTasks, grp);

    ResultsTextBox.Text += string.Format("\r\n#Task assigned for group {0}. Download tasks are active.\r\n", grp);

    // ***This task is complete when a group has finished downloading and displaying.
    await pendingWork;

    // You can do other work here or just return.
    return grp;
}

JJ651641.collapse_all(fr-fr,VS.110).gifLa méthode de FinishOneGroupAsync

Cette méthode parcourt les tâches de téléchargement à un groupe, en attente et, en affichant la longueur du site Web téléchargé, et ajoutant la longueur au total.

La première instruction dans FinishOneGroupAsync utilise pendingWork pour vous assurer que l'écriture la méthode n'interfère avec pas d'opération qui se trouve déjà dans le processus d'affichage ou qui attend déjà.Si une telle opération est en cours, l'exécution entrante doit attendre son tour.

Private Async Function FinishOneGroupAsync(urls As List(Of String), contentTasks As Task(Of Byte())(), grp As Char) As Task

    ' Wait for the previous group to finish displaying results.
    If pendingWork IsNot Nothing Then
        Await pendingWork
    End If

    Dim total = 0

    ' contentTasks is the array of Tasks that was created in AccessTheWebAsync.
    For i As Integer = 0 To contentTasks.Length - 1
        ' Await the download of a particular URL, and then display the URL and
        ' its length.
        Dim content As Byte() = Await contentTasks(i)
        DisplayResults(urls(i), content, i, grp)
        total += content.Length
    Next

    ' Display the total count for all of the websites.
    ResultsTextBox.Text &=
        String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned:  " & total & vbCrLf)
End Function
private async Task FinishOneGroupAsync(List<string> urls, Task<byte[]>[] contentTasks, char grp)
{
    // ***Wait for the previous group to finish displaying results.
    if (pendingWork != null) await pendingWork;

    int total = 0;

    // contentTasks is the array of Tasks that was created in AccessTheWebAsync.
    for (int i = 0; i < contentTasks.Length; i++)
    {
        // Await the download of a particular URL, and then display the URL and
        // its length.
        byte[] content = await contentTasks[i];
        DisplayResults(urls[i], content, i, grp);
        total += content.Length;
    }

    // Display the total count for all of the websites.
    ResultsTextBox.Text +=
        string.Format("\r\n\r\nTOTAL bytes returned:  {0}\r\n", total);
}

Vous pouvez exécuter cet exemple en collant les modifications dans le code de Génération d'Applications, ou vous pouvez suivre les instructions dans Télécharger Applications de télécharger l'exemple, puis de gérer le projet de QueueResults.

JJ651641.collapse_all(fr-fr,VS.110).gifPoints d'intérêt

Les lignes d'information qui commencent par un signe dièse (#) dans la sortie clarifient comment cet exemple fonctionne.

La sortie présente les modèles suivants.

  • Un groupe peut être démarré pendant qu'un groupe précédent affiche la sortie, mais l'affichage de la sortie du groupe précédent n'est pas interrompu.

    #Starting group A.
    #Task assigned for group A. Download tasks are active.
    
    A-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87389
    A-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
    A-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
    A-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119037
    A-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
    
    #Starting group B.
    #Task assigned for group B. Download tasks are active.
    
    A-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
    A-7. msdn.microsoft.com                                            53078
    A-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010
    
    TOTAL bytes returned:  915919
    
    B-1. msdn.microsoft.com/en-us/library/hh191443.aspx                87388
    B-2. msdn.microsoft.com/en-us/library/aa578028.aspx               207089
    B-3. msdn.microsoft.com/en-us/library/jj155761.aspx                30870
    
    #Group A is complete.
    
    B-4. msdn.microsoft.com/en-us/library/hh290140.aspx               119027
    B-5. msdn.microsoft.com/en-us/library/hh524395.aspx                71260
    B-6. msdn.microsoft.com/en-us/library/ms404677.aspx               199186
    B-7. msdn.microsoft.com                                            53078
    B-8. msdn.microsoft.com/en-us/library/ff730837.aspx               148010
    
    TOTAL bytes returned:  915908
    
  • La tâche d' pendingWork est null (Nothing en Visual Basic) au début d' FinishOneGroupAsync uniquement pour le groupe De, qui a démarré en premier.Regroupez A pas encore terminé une expression d'attente lorsqu'il atteint FinishOneGroupAsync.Par conséquent, le contrôle ne s'est pas retourné à AccessTheWebAsync, et le premier assignation à pendingWork ne s'est pas produit.

  • Les deux lignes suivantes s'affichent toujours ensemble de la sortie.Le code n'est jamais interrompu entre le démarrage de l'exécution d'un groupe dans StartButton_Click et assigner une tâche pour le groupe à pendingWork.

    #Starting group B.
    #Task assigned for group B. Download tasks are active.
    

    Une fois un groupe entre dans StartButton_Click, l'opération ne se termine pas une expression d'attente jusqu'à ce que l'exécution entre dans FinishOneGroupAsync.Par conséquent, aucune autre opération ne peut contrôler le volume pendant ce segment de code.

Examen et exécuter l'exemple Applications

Pour mieux comprendre l'exemple d'application, vous pouvez la télécharger, la génération vous-même, ou examinez le code à la fin de cette rubrique sans implémenter l'application.

[!REMARQUE]

Pour exécuter l'exemple comme une application de bureau Windows Presentation Foundation (WPF), vous devez avoir installé Visual Studio 2012 Visual Studio express 2012 pour le bureau Windows, ou .NET Framework 4,5 sur votre ordinateur.

Pour exécuter l'exemple comme une application à Windows Store, vous devez avoir windows 8 installées sur votre ordinateur.En outre, si vous souhaitez exécuter l'exemple Visual Studio, vous devez également avoir Visual Studio 2012 ou Visual Studio express 2012 pour windows 8 installé.Visual Studio 2010 ne peut pas charger les projets qui sont ciblés pour .NET Framework 4,5.

JJ651641.collapse_all(fr-fr,VS.110).gifTélécharger Applications

  1. Téléchargez le fichier compressé dans Exemples Async : Réentrance dans les applications de Bureau .NET ou Exemples Async : Réentrance dans les applications de mémoire windows.

  2. Décompressez le fichier que vous avez téléchargé, puis démarrez Visual Studio.

  3. Dans la barre de menus, sélectionnez Fichier, Ouvrir, Projet/Solution.

  4. Accédez au dossier qui contient l'exemple de code décompressé, puis ouvrez le fichier solution (.sln).

  5. Dans Explorateur de solutions, ouvrez le menu contextuel du projet que vous souhaitez gérer, puis choisissez Affectez comme StartUpProject.

  6. Choisissez les touches CTRL+F5 pour générer et exécuter le projet.

JJ651641.collapse_all(fr-fr,VS.110).gifGénération d'Applications

Les sections suivantes fournissent le code pour créer l'exemple comme une application WPF ou comme une application à Windows Store .

Pour générer une application WPF

  1. Démarrez Visual Studio 2012.

  2. Dans la barre de menus, sélectionnez Fichier, Nouveau, Project.

    La boîte de dialogue Nouveau projet s'affiche.

  3. Dans le volet de Modèles installés, développez Visual Basic ou Visual C#, puis développez Fenêtres.

  4. Dans la liste des types de projets, choisissez Application WPF.

  5. Nommez le projet WebsiteDownloadWPF, puis choisissez le bouton OK .

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

  6. 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 Explorateur de solutions, puis choisissez Afficher le code.

  7. dans la vue XAML de MainWindow.xaml, remplacez le code par le code suivant.

    <Window x:Class="MainWindow"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WebsiteDownloadWPF"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Width="517" Height="360">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="-1,0,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="53" Background="#FFA89B9B" FontSize="36" Width="518"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="-1,53,0,-36" TextWrapping="Wrap" VerticalAlignment="Top" Height="343" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="518" FontFamily="Lucida Console" />
        </Grid>
    </Window>
    
    <Window x:Class="WebsiteDownloadWPF.MainWindow"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WebsiteDownloadWPF"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Width="517" Height="360">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="-1,0,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="53" Background="#FFA89B9B" FontSize="36" Width="518"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="-1,53,0,-36" TextWrapping="Wrap" VerticalAlignment="Top" Height="343" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="518" FontFamily="Lucida Console" />
        </Grid>
    </Window>
    

    Une fenêtre simple qui contient une TextBox et un bouton apparaît dans la vue Design de MainWindow.xaml.

  8. Ajouter la référence System.Net.Http.

  9. Dans L'Explorateur de solutions, ouvrez le menu contextuel pour MainWindow.xaml.vb ou MainWindow.xaml.cs puis choisissez Afficher le Code.

  10. Dans MainWindow.xaml.vb or MainWindow.xaml.cs, remplacez le code par le code suivant.

    ' Add the following Imports statements, and add a reference for System.Net.Http.
    Imports System.Net.Http
    Imports System.Threading
    
    Class MainWindow
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ' This line is commented out to make the results clearer in the output.
            'ResultsTextBox.Text = ""
    
            Try
                Await AccessTheWebAsync()
    
            Catch ex As Exception
                ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    
            End Try
        End Sub
    
    
        Private Async Function AccessTheWebAsync() As Task
    
            ' Declare an HttpClient object.
            Dim client = New HttpClient()
    
            ' Make a list of web addresses.
            Dim urlList As List(Of String) = SetUpURLList()
    
            Dim total = 0
            Dim position = 0
    
            For Each url In urlList
                ' GetByteArrayAsync returns a task. At completion, the task
                ' produces a byte array.
                Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
                position += 1
                DisplayResults(url, urlContents, position)
    
                ' Update the total.
                total += urlContents.Length
            Next
    
            ' Display the total count for all of the websites.
            ResultsTextBox.Text &=
                String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned:  " & total & vbCrLf)
        End Function
    
    
        Private Function SetUpURLList() As List(Of String)
            Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/en-us/library/hh191443.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
            Return urls
        End Function
    
    
        Private Sub DisplayResults(url As String, content As Byte(), pos As Integer)
            ' Display the length of each website. The string format is designed
            ' to be used with a monospaced font, such as Lucida Console or
            ' Global Monospace.
    
            ' Strip off the "http:'".
            Dim displayURL = url.Replace("http://", "")
            ' Display position in the URL list, the URL, and the number of bytes.
            ResultsTextBox.Text &= String.Format(vbCrLf & "{0}. {1,-58} {2,8}", pos, displayURL, content.Length)
        End Sub
    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 the following using directives, and add a reference for System.Net.Http.
    using System.Net.Http;
    using System.Threading;
    
    namespace WebsiteDownloadWPF
    {
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
    
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                // This line is commented out to make the results clearer in the output.
                //ResultsTextBox.Text = "";
    
                try
                {
                    await AccessTheWebAsync();
                }
                catch (Exception)
                {
                    ResultsTextBox.Text += "\r\nDownloads failed.";
                }
            }
    
    
            private async Task AccessTheWebAsync()
            {
                // Declare an HttpClient object.
                HttpClient client = new HttpClient();
    
                // Make a list of web addresses.
                List<string> urlList = SetUpURLList();
    
                var total = 0;
                var position = 0;
    
                foreach (var url in urlList)
                {
                    // GetByteArrayAsync returns a task. At completion, the task
                    // produces a byte array.
                    byte[] urlContents = await client.GetByteArrayAsync(url);
    
                    DisplayResults(url, urlContents, ++position);
    
                    // Update the total.
                    total += urlContents.Length;
                }
    
                // Display the total count for all of the websites.
                ResultsTextBox.Text +=
                    string.Format("\r\n\r\nTOTAL bytes returned:  {0}\r\n", total);
            }
    
    
            private List<string> SetUpURLList()
            {
                List<string> urls = new List<string> 
                { 
                    "https://msdn.microsoft.com/en-us/library/hh191443.aspx",
                    "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                    "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                    "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                    "https://msdn.microsoft.com",
                    "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
                };
                return urls;
            }
    
    
            private void DisplayResults(string url, byte[] content, int pos)
            {
                // Display the length of each website. The string format is designed
                // to be used with a monospaced font, such as Lucida Console or 
                // Global Monospace.
    
                // Strip off the "http://".
                var displayURL = url.Replace("http://", "");
                // Display position in the URL list, the URL, and the number of bytes.
                ResultsTextBox.Text += string.Format("\n{0}. {1,-58} {2,8}", pos, displayURL, content.Length);
            }
        }
    }
    
  11. Choisissez les touches CTRL+F5 pour exécuter le programme, puis choisissez le bouton Démarrer plusieurs fois.

  12. Apportez les modifications de Désactivez le bouton amorçage, de Supprimez et redémarrez l'exécution, ou de Exécuter plusieurs opérations et mettez en file d'attente la sortie pour gérer la réentrance.

Pour créer des fenêtres signalent l'application

  1. Démarrez Visual Studio 2012.

  2. Dans la barre de menus, sélectionnez Fichier, Nouveau, Project.

    La boîte de dialogue Nouveau projet s'affiche.

  3. Dans Installé, la catégorie Modèles, développez Visual Basic ou Visual C#, puis développez Windows Store.

  4. Dans la liste des types de projets, choisissez Application vide (XAML).

  5. Nommez le projet WebsiteDownloadWin, puis choisissez le bouton OK .

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

  6. Dans Explorateur de solutions, ouvrez le menu contextuel pour MainPage.xaml, puis choisissez Ouvrir.

  7. Dans la fenêtre XAML de MainPage.xaml, remplacez le code par le code suivant.

    <Page
        x:Class="WebsiteDownloadWin.MainPage"
        xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WebsiteDownloadWin"
        xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d" FontSize="12">
    
        <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
            <Button x:Name="StartButton" Content="Start" HorizontalAlignment="Left" Margin="325,77,0,0" VerticalAlignment="Top" Click="StartButton_Click" Height="145" Background="#FFA89B9B" FontSize="36" Width="711"  />
            <TextBox x:Name="ResultsTextBox" HorizontalAlignment="Left" Margin="325,222,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Height="546" FontSize="10" ScrollViewer.VerticalScrollBarVisibility="Visible" Width="711" FontFamily="Lucida Console" />
        </Grid>
    </Page>
    

    Une fenêtre simple qui contient une zone de texte et un bouton Démarrer apparaît dans la fenêtre Design de MainPage.xaml.

  8. Dans Explorateur de solutions, ouvrez le menu contextuel pour MainPage.xaml.vb ou MainPage.xaml.cs, puis choisissez Afficher le code.

  9. Remplacez le code dans MainPage.xaml.vb ou MainPage.xaml.cs par le code suivant.

    ' Add the following Imports statements.
    Imports System.Threading.Tasks
    Imports System.Threading
    Imports System.Net.Http
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        Protected Overrides Sub OnNavigatedTo(e As Navigation.NavigationEventArgs)
        End Sub
    
    
        Private Async Sub StartButton_Click(sender As Object, e As RoutedEventArgs)
            ' This line is commented out to make the results clearer in the output.
            'ResultsTextBox.Text = ""
    
            Try
                Await AccessTheWebAsync()
    
            Catch ex As Exception
                ResultsTextBox.Text &= vbCrLf & "Downloads failed."
    
            End Try
        End Sub
    
    
        Private Async Function AccessTheWebAsync() As Task
    
            ' Declare an HttpClient object.
            Dim client = New HttpClient()
    
            ' Make a list of web addresses.
            Dim urlList As List(Of String) = SetUpURLList()
    
            Dim total = 0
            Dim position = 0
    
            For Each url In urlList
                ' GetByteArrayAsync returns a task. At completion, the task
                ' produces a byte array.
                Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
                position += 1
                DisplayResults(url, urlContents, position)
    
                ' Update the total.
                total += urlContents.Length
            Next
    
            ' Display the total count for all of the websites.
            ResultsTextBox.Text &=
                String.Format(vbCrLf & vbCrLf & "TOTAL bytes returned:  " & total & vbCrLf)
        End Function
    
    
        Private Function SetUpURLList() As List(Of String)
            Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/en-us/library/hh191443.aspx",
                "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
            }
            Return urls
        End Function
    
    
        Private Sub DisplayResults(url As String, content As Byte(), pos As Integer)
            ' Display the length of each website. The string format is designed
            ' to be used with a monospaced font, such as Lucida Console or
            ' Global Monospace.
    
            ' Strip off the "http:'".
            Dim displayURL = url.Replace("http://", "")
            ' Display position in the URL list, the URL, and the number of bytes.
            ResultsTextBox.Text &= String.Format(vbCrLf & "{0}. {1,-58} {2,8}", pos, displayURL, content.Length)
        End Sub
    End Class
    
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using Windows.Foundation;
    using Windows.Foundation.Collections;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Controls.Primitives;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Input;
    using Windows.UI.Xaml.Media;
    using Windows.UI.Xaml.Navigation;
    
    // Add the following using directives. 
    using System.Threading.Tasks;
    using System.Threading;
    using System.Net.Http;
    
    
    namespace WebsiteDownloadWin
    {
        public sealed partial class MainPage : Page
        {
            public MainPage()
            {
                this.InitializeComponent();
            }
    
            private async void StartButton_Click(object sender, RoutedEventArgs e)
            {
                // This line is commented out to make the results clearer in the output.
                //ResultsTextBox.Text = "";
    
                try
                {
                    await AccessTheWebAsync();
                }
                catch (Exception)
                {
                    ResultsTextBox.Text += "\r\nDownloads failed.";
                }
            }
    
    
            private async Task AccessTheWebAsync()
            {
                // Declare an HttpClient object.
                HttpClient client = new HttpClient();
    
                // Make a list of web addresses.
                List<string> urlList = SetUpURLList();
    
                var total = 0;
                var position = 0;
    
                foreach (var url in urlList)
                {
                    // GetByteArrayAsync returns a task. At completion, the task
                    // produces a byte array.
                    byte[] urlContents = await client.GetByteArrayAsync(url);
    
                    DisplayResults(url, urlContents, ++position);
    
                    // Update the total.
                    total += urlContents.Length;
                }
    
                // Display the total count for all of the websites.
                ResultsTextBox.Text +=
                    string.Format("\r\n\r\nTOTAL bytes returned:  {0}\r\n", total);
            }
    
    
            private List<string> SetUpURLList()
            {
                List<string> urls = new List<string> 
                { 
                    "https://msdn.microsoft.com/en-us/library/hh191443.aspx",
                    "https://msdn.microsoft.com/en-us/library/aa578028.aspx",
                    "https://msdn.microsoft.com/en-us/library/jj155761.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh290140.aspx",
                    "https://msdn.microsoft.com/en-us/library/hh524395.aspx",
                    "https://msdn.microsoft.com/en-us/library/ms404677.aspx",
                    "https://msdn.microsoft.com",
                    "https://msdn.microsoft.com/en-us/library/ff730837.aspx"
                };
                return urls;
            }
    
    
            private void DisplayResults(string url, byte[] content, int pos)
            {
                // Display the length of each website. The string format is designed
                // to be used with a monospaced font, such as Lucida Console or
                // Global Monospace.
    
                // Strip off the "http://".
                var displayURL = url.Replace("http://", "");
                // Display position in the URL list, the URL, and the number of bytes.
                ResultsTextBox.Text += string.Format("\n{0}. {1,-58} {2,8}", pos, displayURL, content.Length);
            }
        }
    }
    
  10. Choisissez les touches CTRL+F5 pour exécuter le programme, puis choisissez le bouton Démarrer plusieurs fois.

  11. Apportez les modifications de Désactivez le bouton amorçage, de Supprimez et redémarrez l'exécution, ou de Exécuter plusieurs opérations et mettez en file d'attente la sortie pour gérer la réentrance.

Voir aussi

Tâches

Procédure pas à pas : accès au Web avec Async et Await (C# et Visual Basic)

Concepts

Programmation asynchrone avec Async et Await (C# et Visual Basic)

Autres ressources

Programmation asynchrone (les fenêtres stockent des applications)

Démarrage rapide : API d'appel asynchrone en c ou Visual Basic