Share via


Reentrancy verwerken in Async Apps (Visual Basic)

Wanneer u asynchrone code in uw app opneemt, moet u overwegen en mogelijk reentrancy voorkomen, die verwijst naar het opnieuw inschakelen van een asynchrone bewerking voordat deze is voltooid. Als u geen mogelijkheden voor reentrancy identificeert en afhandelt, kan dit onverwachte resultaten veroorzaken.

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.

Notitie

Transport Layer Security (TLS) versie 1.2 is nu de minimale versie die moet worden gebruikt in de ontwikkeling van uw app. Als uw app is gericht op een .NET Framework-versie ouder dan 4.7, raadpleegt u het volgende artikel voor best practices voor Transport Layer Security (TLS) met .NET Framework.

Reentrancy herkennen

In het voorbeeld in dit onderwerp kiezen gebruikers een startknop om een asynchrone app te initiëren waarmee een reeks websites wordt gedownload en het totale aantal gedownloade bytes wordt berekend. Een synchrone versie van het voorbeeld reageert op dezelfde manier, ongeacht hoe vaak een gebruiker de knop kiest, omdat na de eerste keer de UI-thread deze gebeurtenissen negeert totdat de app is uitgevoerd. In een asynchrone app blijft de UI-thread echter reageren en kunt u de asynchrone bewerking opnieuw uitvoeren voordat deze is voltooid.

In het volgende voorbeeld ziet u de verwachte uitvoer als de gebruiker slechts eenmaal de knop Start kiest. Een lijst met de gedownloade websites wordt weergegeven met de grootte, in bytes, van elke site. Het totale aantal bytes wordt aan het einde weergegeven.

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

TOTAL bytes returned:  890591

Als de gebruiker echter meer dan één keer de knop kiest, wordt de gebeurtenis-handler herhaaldelijk aangeroepen en wordt het downloadproces telkens opnieuw uitgevoerd. Als gevolg hiervan worden verschillende asynchrone bewerkingen tegelijkertijd uitgevoerd, de uitvoer interleaseert de resultaten en het totale aantal bytes is verwarrend.

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

TOTAL bytes returned:  890591

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

TOTAL bytes returned:  890591

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

TOTAL bytes returned:  890591

U kunt de code bekijken die deze uitvoer produceert door naar het einde van dit onderwerp te schuiven. U kunt experimenteren met de code door de oplossing naar uw lokale computer te downloaden en vervolgens het Project WebsiteDownload uit te voeren of door de code aan het einde van dit onderwerp te gebruiken om uw eigen project te maken voor meer informatie en instructies, zie De voorbeeld-app controleren en uitvoeren.

Reentrancy verwerken

U kunt reentrancy op verschillende manieren afhandelen, afhankelijk van wat u wilt dat uw app doet. In dit onderwerp worden de volgende voorbeelden weergegeven:

De startknop uitschakelen

U kunt de startknop blokkeren terwijl een bewerking wordt uitgevoerd door de knop boven aan de StartButton_Click gebeurtenis-handler uit te schakelen. U kunt de knop vervolgens opnieuw activeren vanuit een Finally blok wanneer de bewerking is voltooid, zodat gebruikers de app opnieuw kunnen uitvoeren.

De volgende code toont deze wijzigingen, die zijn gemarkeerd met sterretjes. U kunt de wijzigingen aan het einde van dit onderwerp toevoegen aan de code of u kunt de voltooide app downloaden vanuit Async Samples: Reentrancy in .NET Desktop Apps. De projectnaam is 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

Als gevolg van de wijzigingen reageert de knop niet terwijl AccessTheWebAsync de websites worden gedownload, zodat het proces niet opnieuw kan worden doorgevoerd.

De bewerking annuleren en opnieuw starten

In plaats van de startknop uit te schakelen, kunt u de knop actief houden, maar als de gebruiker die knop opnieuw kiest, annuleert u de bewerking die al wordt uitgevoerd en laat u de laatst gestarte bewerking doorgaan.

Zie Uw asynchrone toepassing (Visual Basic) afstemmen voor meer informatie over annulering.

Als u dit scenario wilt instellen, moet u de volgende wijzigingen aanbrengen in de basiscode die is opgegeven in De voorbeeld-app controleren en uitvoeren. U kunt de voltooide app ook downloaden uit Async Samples: Reentrancy in .NET Desktop Apps. De naam van dit project is CancelAndRestart.

  1. Declareer een CancellationTokenSource variabele, ctsdie binnen het bereik van alle methoden valt.

    Class MainWindow // Or Class MainPage
    
        ' *** Declare a System.Threading.CancellationTokenSource.
        Dim cts As CancellationTokenSource
    
  2. Bepaal StartButton_Clickin of er al een bewerking wordt uitgevoerd. Als de waarde cts is Nothing, is er al geen bewerking actief. Als de waarde niet Nothingis, wordt de bewerking die al wordt uitgevoerd, geannuleerd.

    ' *** If a download process is already underway, cancel it.
    If cts IsNot Nothing Then
        cts.Cancel()
    End If
    
  3. Instellen cts op een andere waarde die het huidige proces vertegenwoordigt.

    ' *** Now set cts to cancel the current process if the button is chosen again.
    Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
    cts = newCTS
    
  4. Aan het einde van StartButton_Clickhet proces is het huidige proces voltooid, dus stel de waarde van cts terug naar Nothing.

    ' *** When the process completes, signal that another process can proceed.
    If cts Is newCTS Then
        cts = Nothing
    End If
    

De volgende code toont alle wijzigingen in StartButton_Click. De toevoegingen zijn gemarkeerd met sterretjes.

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

Breng AccessTheWebAsyncde volgende wijzigingen aan.

  • Voeg een parameter toe om het annuleringstoken van te accepteren.StartButton_Click

  • Gebruik de GetAsync methode om de websites te downloaden omdat GetAsync er een CancellationToken argument wordt geaccepteerd.

  • Voordat u aanroept DisplayResults om de resultaten voor elke gedownloade website weer te geven, controleert ct u of de huidige bewerking niet is geannuleerd.

De volgende code toont deze wijzigingen, die zijn gemarkeerd met sterretjes.

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

Als u de knop Start meerdere keren kiest terwijl deze app wordt uitgevoerd, moet deze resultaten opleveren die lijken op de volgende uitvoer:

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

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

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

TOTAL bytes returned:  890591

Als u de gedeeltelijke lijsten wilt elimineren, verwijdert u de opmerkingen bij de eerste regel code om StartButton_Click het tekstvak te wissen telkens wanneer de gebruiker de bewerking opnieuw start.

Meerdere bewerkingen uitvoeren en de uitvoer in de wachtrij plaatsen

Dit derde voorbeeld is het ingewikkeldst omdat de app telkens wanneer de gebruiker de knop Start kiest, een andere asynchrone bewerking start en alle bewerkingen worden uitgevoerd tot voltooiing. Alle aangevraagde bewerkingen downloaden websites asynchroon uit de lijst, maar de uitvoer van de bewerkingen wordt opeenvolgend weergegeven. Dat wil gezegd, de werkelijke downloadactiviteit is interleaved, zoals de uitvoer in Het herkennen van reentrancy weergeeft, maar de lijst met resultaten voor elke groep afzonderlijk wordt weergegeven.

De bewerkingen delen een globaal Task, pendingWorkdat fungeert als gatekeeper voor het weergaveproces.

U kunt dit voorbeeld uitvoeren door de wijzigingen in de code in de app te plakken. U kunt ook de instructies volgen in De app downloaden om het voorbeeld te downloaden en vervolgens het QueueResults-project uit te voeren.

In de volgende uitvoer ziet u het resultaat als de gebruiker slechts eenmaal de knop Start kiest. Het letterlabel, A, geeft aan dat het resultaat afkomstig is van de eerste keer dat de knop Start wordt gekozen. De getallen geven de volgorde weer van de URL's in de lijst met downloaddoelen.

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

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

TOTAL bytes returned:  918876

#Group A is complete.

Als de gebruiker drie keer de startknop kiest, produceert de app uitvoer die lijkt op de volgende regels. De informatieregels die beginnen met een hekje (#) traceren de voortgang van de toepassing.

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

A-1. msdn.microsoft.com/library/hh191443.aspx                87389
A-2. msdn.microsoft.com/library/aa578028.aspx               207089
A-3. msdn.microsoft.com/library/jj155761.aspx                30870
A-4. msdn.microsoft.com/library/hh290140.aspx               119027
A-5. msdn.microsoft.com/library/hh524395.aspx                71259
A-6. msdn.microsoft.com/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/library/ff730837.aspx               148010

TOTAL bytes returned:  916095

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

#Group A is complete.

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

TOTAL bytes returned:  916097

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

#Group B is complete.

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

TOTAL bytes returned:  920526

#Group C is complete.

Groepen B en C beginnen voordat groep A is voltooid, maar de uitvoer voor elke groep wordt afzonderlijk weergegeven. Alle uitvoer voor groep A wordt eerst weergegeven, gevolgd door alle uitvoer voor groep B en vervolgens alle uitvoer voor groep C. In de app worden altijd de groepen in volgorde weergegeven en voor elke groep wordt altijd de informatie over de afzonderlijke websites weergegeven in de volgorde waarin de URL's worden weergegeven in de lijst met URL's.

U kunt echter niet voorspellen in welke volgorde de downloads daadwerkelijk plaatsvinden. Nadat meerdere groepen zijn gestart, zijn de downloadtaken die ze genereren allemaal actief. U kunt er niet van uitgaan dat A-1 wordt gedownload voor B-1 en u kunt er niet van uitgaan dat A-1 vóór A-2 wordt gedownload.

Globale definities

De voorbeeldcode bevat de volgende twee globale declaraties die zichtbaar zijn voor alle methoden.

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)

De Task variabele, pendingWorkhoudt toezicht op het weergaveproces en voorkomt dat een groep de weergavebewerking van een andere groep onderbreekt. De tekenvariabele, grouplabelt de uitvoer van verschillende groepen om te controleren of de resultaten in de verwachte volgorde worden weergegeven.

De gebeurtenis-handler klikken

Met de gebeurtenis-handler StartButton_Clickwordt de groepsletter verhoogd telkens wanneer de gebruiker de knop Start kiest. Vervolgens roept AccessTheWebAsync de handler aan om de downloadbewerking uit te voeren.

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

De methode AccessTheWebAsync

In dit voorbeeld worden twee methoden onderverdeeld AccessTheWebAsync . Met de eerste methode worden AccessTheWebAsyncalle downloadtaken voor een groep gestart en ingesteld pendingWork om het weergaveproces te beheren. De methode maakt gebruik van een LINQ-query (Language Integrated Query) en ToArray om alle downloadtaken tegelijkertijd te starten.

AccessTheWebAsyncFinishOneGroupAsync roept vervolgens aan om te wachten op de voltooiing van elke download en de lengte ervan weer te geven.

FinishOneGroupAsync retourneert een taak waaraan is toegewezen pendingWork in AccessTheWebAsync. Deze waarde voorkomt onderbreking door een andere bewerking voordat de taak is voltooid.

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

De methode FinishOneGroupAsync

Deze methode doorloopt de downloadtaken in een groep, wacht op elke groep, geeft de lengte van de gedownloade website weer en voegt de lengte toe aan het totaal.

De eerste instructie in FinishOneGroupAsync gebruik pendingWork om ervoor te zorgen dat het invoeren van de methode geen invloed heeft op een bewerking die zich al in het weergaveproces bevindt of die al wacht. Als een dergelijke bewerking wordt uitgevoerd, moet de invoerbewerking zijn beurt wachten.

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

U kunt dit voorbeeld uitvoeren door de wijzigingen in de code in de app te plakken. U kunt ook de instructies volgen in De app downloaden om het voorbeeld te downloaden en vervolgens het QueueResults-project uit te voeren.

Speciale punten

De informatieregels die beginnen met een hekje (#) in de uitvoer verduidelijken hoe dit voorbeeld werkt.

In de uitvoer ziet u de volgende patronen.

  • Een groep kan worden gestart terwijl een vorige groep de uitvoer weergeeft, maar de weergave van de uitvoer van de vorige groep wordt niet onderbroken.

    #Starting group A.
    #Task assigned for group A. Download tasks are active.
    
    A-1. msdn.microsoft.com/library/hh191443.aspx                87389
    A-2. msdn.microsoft.com/library/aa578028.aspx               207089
    A-3. msdn.microsoft.com/library/jj155761.aspx                30870
    A-4. msdn.microsoft.com/library/hh290140.aspx               119037
    A-5. msdn.microsoft.com/library/hh524395.aspx                71260
    
    #Starting group B.
    #Task assigned for group B. Download tasks are active.
    
    A-6. msdn.microsoft.com/library/ms404677.aspx               199186
    A-7. msdn.microsoft.com                                            53078
    A-8. msdn.microsoft.com/library/ff730837.aspx               148010
    
    TOTAL bytes returned:  915919
    
    B-1. msdn.microsoft.com/library/hh191443.aspx                87388
    B-2. msdn.microsoft.com/library/aa578028.aspx               207089
    B-3. msdn.microsoft.com/library/jj155761.aspx                30870
    
    #Group A is complete.
    
    B-4. msdn.microsoft.com/library/hh290140.aspx               119027
    B-5. msdn.microsoft.com/library/hh524395.aspx                71260
    B-6. msdn.microsoft.com/library/ms404677.aspx               199186
    B-7. msdn.microsoft.com                                            53078
    B-8. msdn.microsoft.com/library/ff730837.aspx               148010
    
    TOTAL bytes returned:  915908
    
  • De pendingWork taak bevindt zich Nothing aan het begin van FinishOneGroupAsync alleen voor groep A, die eerst is gestart. Groep A heeft nog geen wachtexpressie voltooid wanneer deze wordt bereikt FinishOneGroupAsync. Daarom is het besturingselement niet teruggezet naar AccessTheWebAsyncen is de eerste toewijzing pendingWork niet opgetreden.

  • De volgende twee regels worden altijd samen weergegeven in de uitvoer. De code wordt nooit onderbroken tussen het starten van de bewerking van een groep in StartButton_Click en het toewijzen van een taak aan pendingWorkde groep.

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

    Nadat een groep is binnenkomt StartButton_Click, wordt een wachtexpressie pas voltooid als de bewerking wordt FinishOneGroupAsyncuitgevoerd. Daarom kan geen andere bewerking controle krijgen tijdens dat codesegment.

De voorbeeld-app controleren en uitvoeren

Als u de voorbeeld-app beter wilt begrijpen, kunt u deze downloaden, zelf bouwen of de code aan het einde van dit onderwerp bekijken zonder de app te implementeren.

Notitie

Als u het voorbeeld wilt uitvoeren als een WPF-bureaublad-app (Windows Presentation Foundation), moet Visual Studio 2012 of hoger en .NET Framework 4.5 of hoger op uw computer zijn geïnstalleerd.

De app downloaden

  1. Download het gecomprimeerde bestand uit Async Samples: Reentrancy in .NET Desktop Apps.

  2. Decomprim het bestand dat u hebt gedownload en start Vervolgens Visual Studio.

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

  4. Navigeer naar de map met de gedecomprimeerde voorbeeldcode en open het oplossingsbestand (.sln).

  5. Open in Solution Explorer het snelmenu voor het project dat u wilt uitvoeren en kies Instellen als StartUpProject.

  6. Kies de Ctrl+F5-toetsen om het project te bouwen en uit te voeren.

De app bouwen

De volgende sectie bevat de code voor het bouwen van het voorbeeld als een WPF-app.

Een WPF-app bouwen
  1. Start Visual Studio.

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

    Het dialoogvenster Nieuw project wordt geopend.

  3. Vouw Visual Basic uit in het deelvenster Geïnstalleerde sjablonen en vouw Vervolgens Windows uit.

  4. Kies WPF-toepassing in de lijst met projecttypen.

  5. Geef het project WebsiteDownloadWPFeen naam, kies .NET Framework-versie 4.6 of hoger en klik vervolgens op de knop OK .

    Het nieuwe project wordt weergegeven in Solution Explorer.

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

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

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:WebsiteDownloadWPF"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://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>
    

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

  8. Klik in Solution Explorer met de rechtermuisknop op Verwijzingen en selecteer Verwijzing toevoegen.

    Voeg een verwijzing toe voor System.Net.Http, als deze nog niet is geselecteerd.

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

  10. Vervang in MainWindow.xaml.vb de code door de volgende code.

    ' 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)
            System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol Or System.Net.SecurityProtocolType.Tls12
    
            ' 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/library/hh191443.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/jj155761.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/hh524395.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/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("https://", "")
            ' 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
    
  11. Kies de Ctrl+F5-toetsen om het programma uit te voeren en kies vervolgens meerdere keren de startknop.

  12. Breng de wijzigingen aan via de startknop uitschakelen, de bewerking annuleren en opnieuw starten, of voer meerdere bewerkingen uit en plaats de uitvoer in de wachtrij om de re-trancy af te handelen.

Zie ook