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 medan åtgärden körs så att användaren inte kan avbryta den.
-
Avbryt alla åtgärder som fortfarande körs när användaren väljer knappen Starta igen och låt sedan den senast begärda åtgärden fortsätta.
Kör flera åtgärder och placera utdata i kö
Tillåt att alla begärda åtgärder körs asynkront, men samordna visning av utdata så att resultatet från varje åtgärd visas tillsammans och i ordning.
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.
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
I
StartButton_Click
avgör du om en åtgärd redan pågår. Om värdetcts
för är ärNothing
är ingen åtgärd redan aktiv. Om värdet inteNothing
ä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
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
I slutet av
StartButton_Click
är den aktuella processen klar, så ange värdetcts
för tillbaka tillNothing
.' *** 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 AccessTheWebAsync
gö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 webbplatsct
.
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 , group
etiketterar 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
ärNothing
i början avFinishOneGroupAsync
endast för grupp A, som startade först. Grupp A har ännu inte slutfört ett väntande uttryck när det nårFinishOneGroupAsync
. Kontrollen har därför inte returnerats tillAccessTheWebAsync
, och den första tilldelningen tillpendingWork
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 tillpendingWork
.#Starting group B. #Task assigned for group B. Download tasks are active.
När en grupp har angetts
StartButton_Click
slutför åtgärden inte ett inväntningsuttryck förrän åtgärden har angettsFinishOneGroupAsync
. 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
Ladda ned den komprimerade filen från Async Samples: Reentrancy i .NET Desktop Apps.
Expandera filen som du laddade ned och starta sedan Visual Studio.
På menyraden väljer du Arkiv, Öppna, Projekt/Lösning.
Gå till mappen som innehåller den dekomprimerade exempelkoden och öppna sedan lösningens fil (.sln).
Öppna snabbmenyn för det projekt som du vill köra i Solution Explorer och välj sedan Ange som StartUpProject.
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
Starta Visual Studio.
På menyraden väljer du Arkiv, Nytt, Projekt.
Dialogrutan Nytt projekt öppnas.
I fönstret Installerade mallar expanderar du Visual Basic och expanderar sedan Windows.
I listan över projekttyper väljer du WPF-program.
Ge projektet
WebsiteDownloadWPF
namnet , välj .NET Framework-versionen 4.6 eller senare och klicka sedan på ok-knappen .Det nya projektet visas i Solution Explorer.
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.
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.
Högerklicka på 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.
Öppna snabbmenyn för MainWindow.xaml.vb i Solution Explorer och välj sedan Visa kod.
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
Välj CTRL+F5-tangenterna för att köra programmet och välj sedan startknappen flera gånger.
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.