Share via


Hantera återaktivering i Async-appar (Visual Basic)

När du inkluderar asynkron kod i din app bör du överväga och eventuellt förhindra återaktivering, vilket refererar till att återaktivera en asynkron åtgärd innan den har slutförts. Om du inte identifierar och hanterar möjligheter till återaktivering kan det orsaka oväntade resultat.

Kommentar

Om du vill köra exemplet måste du ha Visual Studio 2012 eller senare och .NET Framework 4.5 eller senare installerat på datorn.

Kommentar

Transport Layer Security (TLS) version 1.2 är nu den lägsta versionen som ska användas i din apputveckling. Om din app har en tidigare .NET Framework-version än 4.7 kan du läsa följande artikel för metodtips för Transport Layer Security (TLS) med .NET Framework.

Känna igen återaktivering

I exemplet i det här avsnittet väljer användarna en Start-knapp för att initiera en asynkron app som laddar ned en serie webbplatser och beräknar det totala antalet byte som laddas ned. En synkron version av exemplet skulle svara på samma sätt oavsett hur många gånger en användare väljer knappen eftersom användargränssnittstråden efter första gången ignorerar dessa händelser tills appen är klar. I en asynkron app fortsätter dock användargränssnittstråden att svara och du kan komma att använda den asynkrona åtgärden igen innan den har slutförts.

I följande exempel visas förväntade utdata om användaren väljer knappen Starta bara en gång. En lista över de nedladdade webbplatserna visas med storleken, i byte, på varje webbplats. Det totala antalet byte visas i slutet.

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

Men om användaren väljer knappen mer än en gång anropas händelsehanteraren upprepade gånger och nedladdningsprocessen skickas igen varje gång. Därför körs flera asynkrona åtgärder samtidigt, utdata mellanläser resultatet och det totala antalet byte är förvirrande.

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

Du kan granska koden som genererar dessa utdata genom att rulla till slutet av det här avsnittet. Du kan experimentera med koden genom att ladda ned lösningen till din lokala dator och sedan köra projektet WebsiteDownload eller genom att använda koden i slutet av det här avsnittet för att skapa ett eget projekt Mer information och instruktioner finns i Granska och köra exempelappen.

Hantering av återaktivering

Du kan hantera återaktivering på flera olika sätt, beroende på vad du vill att din app ska göra. I det här avsnittet visas följande exempel:

Inaktivera startknappen

Du kan blockera startknappen medan en åtgärd körs genom att inaktivera knappen överst i StartButton_Click händelsehanteraren. Du kan sedan återaktivera knappen inifrån ett Finally block när åtgärden är klar så att användarna kan köra appen igen.

Följande kod visar dessa ändringar, som är markerade med asterisker. Du kan lägga till ändringarna i koden i slutet av det här avsnittet, eller så kan du ladda ned den färdiga appen från Async Samples: Reentrancy i .NET Desktop Apps. Projektnamnet är 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

Som ett resultat av ändringarna svarar inte knappen när AccessTheWebAsync webbplatserna laddas ned, så processen kan inte skickas igen.

Avbryt och starta om åtgärden

I stället för att inaktivera startknappen kan du hålla knappen aktiv, men om användaren väljer den knappen igen avbryter du den åtgärd som redan körs och låter den senast startade åtgärden fortsätta.

Mer information om annullering finns i Finjustera ditt Async-program (Visual Basic).

Konfigurera det här scenariot genom att göra följande ändringar i den grundläggande kod som anges i Granska och köra exempelappen. Du kan också ladda ned den färdiga appen från Async Samples: Reentrancy i .NET Desktop Apps. Namnet på projektet är CancelAndRestart.

  1. Deklarera en CancellationTokenSource variabel, cts, som finns i omfånget för alla metoder.

    Class MainWindow // Or Class MainPage
    
        ' *** Declare a System.Threading.CancellationTokenSource.
        Dim cts As CancellationTokenSource
    
  2. I StartButton_Clickavgör du om en åtgärd redan pågår. Om värdet cts för är är Nothingär ingen åtgärd redan aktiv. Om värdet inte Nothingär avbryts den åtgärd som redan körs.

    ' *** If a download process is already underway, cancel it.
    If cts IsNot Nothing Then
        cts.Cancel()
    End If
    
  3. Ange cts till ett annat värde som representerar den aktuella processen.

    ' *** Now set cts to cancel the current process if the button is chosen again.
    Dim newCTS As CancellationTokenSource = New CancellationTokenSource()
    cts = newCTS
    
  4. I slutet av StartButton_Clickär den aktuella processen klar, så ange värdet cts för tillbaka till Nothing.

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

Följande kod visar alla ändringar i StartButton_Click. Tilläggen är markerade med asterisker.

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

I AccessTheWebAsyncgör du följande ändringar.

  • Lägg till en parameter för att acceptera annulleringstoken från StartButton_Click.

  • GetAsync Använd metoden för att ladda ned webbplatserna eftersom GetAsync accepterar ett CancellationToken argument.

  • Kontrollera att den aktuella åtgärden inte har avbrutits innan du anropar DisplayResults för att visa resultatet för varje nedladdad webbplats ct .

Följande kod visar dessa ändringar, som är markerade med asterisker.

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

Om du väljer startknappen flera gånger medan den här appen körs bör den ge resultat som liknar följande utdata:

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

Ta bort de partiella listorna genom att ta bort den första kodraden för StartButton_Click att rensa textrutan varje gång användaren startar om åtgärden.

Kör flera åtgärder och placera utdata i kö

Det tredje exemplet är det mest komplicerade i och med att appen startar en annan asynkron åtgärd varje gång användaren väljer startknappen och alla åtgärder körs till slutförande. Alla begärda åtgärder laddar ned webbplatser från listan asynkront, men utdata från åtgärderna visas sekventiellt. Det innebär att den faktiska nedladdningsaktiviteten interleaved, som utdata i Recognizing Reentrancy visar, men listan med resultat för varje grupp presenteras separat.

Åtgärderna delar en global Task, pendingWork, som fungerar som en gatekeeper för visningsprocessen.

Du kan köra det här exemplet genom att klistra in ändringarna i koden i Skapa appen, eller så kan du följa anvisningarna i Ladda ned appen för att ladda ned exemplet och sedan köra QueueResults-projektet.

Följande utdata visar resultatet om användaren väljer knappen Starta bara en gång. Bokstavsetiketten A anger att resultatet är från första gången knappen Start väljs. Siffrorna visar ordningen på URL:erna i listan över nedladdningsmål.

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

Om användaren väljer knappen Start tre gånger skapar appen utdata som liknar följande rader. Informationsraderna som börjar med ett pundtecken (#) spårar programmets förlopp.

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

Grupper B och C startar innan grupp A har slutförts, men utdata för varje grupp visas separat. Alla utdata för grupp A visas först, följt av alla utdata för grupp B och sedan alla utdata för grupp C. Appen visar alltid grupperna i ordning och visar alltid information om de enskilda webbplatserna i den ordning som URL:erna visas i listan över URL:er för varje grupp.

Du kan dock inte förutsäga i vilken ordning nedladdningarna faktiskt sker. När flera grupper har startats är alla nedladdningsuppgifter som de genererar aktiva. Du kan inte anta att A-1 laddas ned före B-1 och du kan inte anta att A-1 laddas ned före A-2.

Globala definitioner

Exempelkoden innehåller följande två globala deklarationer som är synliga från alla metoder.

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)

Variabeln Task , pendingWork, övervakar visningsprocessen och förhindrar att någon grupp avbryter en annan grupps visningsåtgärd. Teckenvariabeln , groupetiketterar utdata från olika grupper för att verifiera att resultatet visas i förväntad ordning.

Klicka på händelsehanteraren

Händelsehanteraren StartButton_Click, , ökar gruppbokstaven varje gång användaren väljer knappen Start . Sedan anropar AccessTheWebAsync hanteraren för att köra nedladdningsåtgärden.

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

Metoden AccessTheWebAsync

Det här exemplet delas upp AccessTheWebAsync i två metoder. Den första metoden, AccessTheWebAsync, startar alla nedladdningsuppgifter för en grupp och konfigurerar pendingWork för att styra visningsprocessen. Metoden använder en språkintegrerad fråga (LINQ-fråga) och ToArray för att starta alla nedladdningsuppgifter samtidigt.

AccessTheWebAsync anropar FinishOneGroupAsync sedan för att invänta slutförandet av varje nedladdning och visa dess längd.

FinishOneGroupAsync returnerar en aktivitet som har tilldelats till pendingWork i AccessTheWebAsync. Det värdet förhindrar avbrott av en annan åtgärd innan aktiviteten är klar.

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

Metoden FinishOneGroupAsync

Den här metoden går igenom nedladdningsuppgifterna i en grupp, väntar på var och en, visar längden på den nedladdade webbplatsen och lägger till längden på summan.

Den första instruktionen i FinishOneGroupAsync används pendingWork för att se till att inmatningen av metoden inte stör en åtgärd som redan är i visningsprocessen eller som redan väntar. Om en sådan åtgärd pågår måste inmatningsåtgärden vänta på sin tur.

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

Du kan köra det här exemplet genom att klistra in ändringarna i koden i Skapa appen, eller så kan du följa anvisningarna i Ladda ned appen för att ladda ned exemplet och sedan köra QueueResults-projektet.

Intressanta punkter

De informationsrader som börjar med ett pundtecken (#) i utdata klargör hur det här exemplet fungerar.

Utdata visar följande mönster.

  • En grupp kan startas medan en tidigare grupp visar sina utdata, men visningen av föregående grupps utdata avbryts inte.

    #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
    
  • Aktiviteten pendingWork är Nothing i början av FinishOneGroupAsync endast för grupp A, som startade först. Grupp A har ännu inte slutfört ett väntande uttryck när det når FinishOneGroupAsync. Kontrollen har därför inte returnerats till AccessTheWebAsync, och den första tilldelningen till pendingWork har inte inträffat.

  • Följande två rader visas alltid tillsammans i utdata. Koden avbryts aldrig mellan att starta en grupps åtgärd i StartButton_Click och tilldela en aktivitet för gruppen till pendingWork.

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

    När en grupp har angetts StartButton_Clickslutför åtgärden inte ett inväntningsuttryck förrän åtgärden har angetts FinishOneGroupAsync. Därför kan ingen annan åtgärd få kontroll under det kodsegmentet.

Granska och köra exempelappen

För att bättre förstå exempelappen kan du ladda ned den, skapa den själv eller granska koden i slutet av det här avsnittet utan att implementera appen.

Kommentar

Om du vill köra exemplet som en WPF-skrivbordsapp (Windows Presentation Foundation) måste du ha Visual Studio 2012 eller senare och .NET Framework 4.5 eller senare installerat på datorn.

Ladda ned appen

  1. Ladda ned den komprimerade filen från Async Samples: Reentrancy i .NET Desktop Apps.

  2. Expandera filen som du laddade ned och starta sedan Visual Studio.

  3. På menyraden väljer du Arkiv, Öppna, Projekt/Lösning.

  4. Gå till mappen som innehåller den dekomprimerade exempelkoden och öppna sedan lösningens fil (.sln).

  5. Öppna snabbmenyn för det projekt som du vill köra i Solution Explorer och välj sedan Ange som StartUpProject.

  6. Välj CTRL+F5-tangenterna för att skapa och köra projektet.

Skapa appen

Följande avsnitt innehåller koden för att skapa exemplet som en WPF-app.

Så här skapar du en WPF-app
  1. Starta Visual Studio.

  2. På menyraden väljer du Arkiv, Nytt, Projekt.

    Dialogrutan Nytt projekt öppnas.

  3. I fönstret Installerade mallar expanderar du Visual Basic och expanderar sedan Windows.

  4. I listan över projekttyper väljer du WPF-program.

  5. Ge projektet WebsiteDownloadWPFnamnet , välj .NET Framework-versionen 4.6 eller senare och klicka sedan på ok-knappen .

    Det nya projektet visas i Solution Explorer.

  6. I Visual Studio Code-redigeraren väljer du fliken MainWindow.xaml .

    Om fliken inte visas öppnar du snabbmenyn för MainWindow.xaml i Solution Explorer och väljer sedan Visa kod.

  7. I XAML-vyn i MainWindow.xaml ersätter du koden med följande kod.

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

    Ett enkelt fönster som innehåller en textruta och en knapp visas i designvyn för MainWindow.xaml.

  8. Högerklicka Referenser i Solution Explorer och välj Lägg till referens.

    Lägg till en referens för System.Net.Http, om den inte redan är markerad.

  9. Öppna snabbmenyn för MainWindow.xaml.vb i Solution Explorer och välj sedan Visa kod.

  10. I MainWindow.xaml.vb ersätter du koden med följande kod.

    ' 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. Välj CTRL+F5-tangenterna för att köra programmet och välj sedan startknappen flera gånger.

  12. Gör ändringarna från Inaktivera startknappen, Avbryt och starta om åtgärden eller Kör flera åtgärder och placera utdata i kö för att hantera återaktiveringen.

Se även