Dela via


Genomgång: Åtkomst till webben med hjälp av Async och Await (Visual Basic)

Du kan skriva asynkrona program enklare och intuitivt med hjälp av funktionerna async/await. Du kan skriva asynkron kod som ser ut som synkron kod och låta kompilatorn hantera de svåra återanropsfunktioner och fortsättningar som asynkron kod vanligtvis medför.

Mer information om funktionen Async finns i Asynkron programmering med Async och Await (Visual Basic).

Den här genomgången börjar med ett synkront WPF-program (Windows Presentation Foundation) som summerar antalet byte i en lista över webbplatser. Genomgången konverterar sedan programmet till en asynkron lösning med hjälp av de nya funktionerna.

Du kan utveckla programmen genom att antingen slutföra genomgången eller ladda ned exemplet från .NET Sample Browser. Exempelkoden finns i SerialAsyncExample-projektet .

I den här genomgången utför du följande uppgifter:

Se avsnittet Exempel för det fullständiga asynkrona exemplet.

Förutsättningar

Visual Studio 2012 eller senare måste vara installerat på datorn. Mer information finns på sidan för Visual Studio-nedladdningar.

Skapa ett WPF-program

  1. Starta Visual Studio.

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

    Dialogrutan Nytt projekt öppnas.

  3. I fönstret Installerade mallar väljer du Visual Basic och sedan WPF-program i listan över projekttyper.

  4. I textrutan Namn anger du AsyncExampleWPFoch väljer sedan knappen OK.

    Det nya projektet visas i Solution Explorer.

Utforma en enkel WPF MainWindow

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

  2. Om fönstret Verktygslåda inte visas öppnar du menyn Visa och väljer sedan Verktygslåda.

  3. Lägg till en knappkontroll och en Textbox-kontroll i MainWindow-fönstret.

  4. Markera textrutekontrollen och ange följande värden i fönstret Egenskaper:

    • Ange egenskapen Namn till resultsTextBox.

    • Ange egenskapen Height till 250.

    • Ange egenskapen Width till 500.

    • På fliken Text anger du ett teckensnitt med monorymd, till exempel Lucida Console eller Global monospace.

  5. Markera knappkontrollen och ange följande värden i fönstret Egenskaper:

    • Ange egenskapen Namn till startButton.

    • Ändra värdet för egenskapen Innehåll från Knapp till Start.

  6. Placera textrutan och knappen så att båda visas i MainWindow-fönstret .

    Mer information om WPF XAML Designer finns i Skapa ett användargränssnitt med XAML Designer.

Lägga till en referens

  1. Markera projektets namn i Solution Explorer.

  2. På menyraden väljer du Projekt, Lägg till referens.

    Dialogrutan Referenshanterare visas.

  3. Kontrollera att projektet är riktat mot .NET Framework 4.5 eller senare överst i dialogrutan.

  4. I området Sammansättningar väljer du Ramverk om det inte redan har valts.

  5. Markera kryssrutan System.Net.Http i listan med namn.

  6. Välj ok-knappen för att stänga dialogrutan.

Lägga till nödvändiga importinstruktioner

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

  2. Lägg till följande Imports instruktioner överst i kodfilen om de inte redan finns.

    Imports System.Net.Http
    Imports System.Net
    Imports System.IO
    

Skapa ett synkront program

  1. I designfönstret MainWindow.xaml dubbelklickar du på knappen Start för att skapa startButton_Click händelsehanteraren i MainWindow.xaml.vb.

  2. I MainWindow.xaml.vb kopierar du följande kod till brödtexten startButton_Clicki :

    resultsTextBox.Clear()
    SumPageSizes()
    resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
    

    Koden anropar den metod som driver programmet och SumPageSizesvisar ett meddelande när kontrollen återgår till startButton_Click.

  3. Koden för den synkrona lösningen innehåller följande fyra metoder:

    • SumPageSizes, som hämtar en lista över url:er för webbsidor från SetUpURLList och sedan anropar GetURLContents och DisplayResults bearbetar varje URL.

    • SetUpURLList, som skapar och returnerar en lista med webbadresser.

    • GetURLContents, som laddar ned innehållet på varje webbplats och returnerar innehållet som en bytematris.

    • DisplayResults, som visar antalet byte i bytematrisen för varje URL.

    Kopiera följande fyra metoder och klistra sedan in dem under startButton_Click händelsehanteraren i MainWindow.xaml.vb:

    Private Sub SumPageSizes()
    
        ' Make a list of web addresses.
        Dim urlList As List(Of String) = SetUpURLList()
    
        Dim total = 0
        For Each url In urlList
            ' GetURLContents returns the contents of url as a byte array.
            Dim urlContents As Byte() = GetURLContents(url)
    
            DisplayResults(url, urlContents)
    
            ' Update the total.
            total += urlContents.Length
        Next
    
        ' Display the total count for all of the web addresses.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf & "Total bytes returned:  {0}" & vbCrLf, total)
    End Sub
    
    Private Function SetUpURLList() As List(Of String)
    
        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/library/ff730837.aspx"
            }
        Return urls
    End Function
    
    Private Function GetURLContents(url As String) As Byte()
    
        ' The downloaded resource ends up in the variable named content.
        Dim content = New MemoryStream()
    
        ' Initialize an HttpWebRequest for the current URL.
        Dim webReq = CType(WebRequest.Create(url), HttpWebRequest)
    
        ' Send the request to the Internet resource and wait for
        ' the response.
        ' Note: you can't use HttpWebRequest.GetResponse in a Windows Store app.
        Using response As WebResponse = webReq.GetResponse()
            ' Get the data stream that is associated with the specified URL.
            Using responseStream As Stream = response.GetResponseStream()
                ' Read the bytes in responseStream and copy them to content.
                responseStream.CopyTo(content)
            End Using
        End Using
    
        ' Return the result as a byte array.
        Return content.ToArray()
    End Function
    
    Private Sub DisplayResults(url As String, content As Byte())
    
        ' 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.
        Dim bytes = content.Length
        ' Strip off the "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub
    

Testa den synkrona lösningen

  1. Välj F5-tangenten för att köra programmet och välj sedan knappen Start .

    Utdata som liknar följande lista bör visas:

    msdn.microsoft.com/library/windows/apps/br211380.aspx        383832
    msdn.microsoft.com                                            33964
    msdn.microsoft.com/library/hh290136.aspx               225793
    msdn.microsoft.com/library/ee256749.aspx               143577
    msdn.microsoft.com/library/hh290138.aspx               237372
    msdn.microsoft.com/library/hh290140.aspx               128279
    msdn.microsoft.com/library/dd470362.aspx               157649
    msdn.microsoft.com/library/aa578028.aspx               204457
    msdn.microsoft.com/library/ms404677.aspx               176405
    msdn.microsoft.com/library/ff730837.aspx               143474
    
    Total bytes returned:  1834802
    
    Control returned to startButton_Click.
    

    Observera att det tar några sekunder att visa antalet. Under den tiden blockeras användargränssnittstråden medan den väntar på att begärda resurser ska laddas ned. Därför kan du inte flytta, maximera, minimera eller ens stänga visningsfönstret när du har valt startknappen . Dessa ansträngningar misslyckas tills byteantalet börjar visas. Om en webbplats inte svarar har du ingen indikation på vilken webbplats som misslyckades. Det är svårt att ens sluta vänta och stänga programmet.

Konvertera GetURLContents till en asynkron metod

  1. Om du vill konvertera den synkrona lösningen till en asynkron lösning är det bästa stället att börja på GetURLContents eftersom anropen HttpWebRequest.GetResponse till metoden och till Stream.CopyTo metoden är där programmet kommer åt webben. .NET Framework gör konverteringen enkel genom att tillhandahålla asynkrona versioner av båda metoderna.

    Mer information om de metoder som används i finns WebRequesti GetURLContents.

    Kommentar

    När du följer stegen i den här genomgången visas flera kompilatorfel. Du kan ignorera dem och fortsätta med genomgången.

    Ändra den metod som anropas på den tredje raden GetURLContents i från GetResponse till den asynkrona, uppgiftsbaserade GetResponseAsync metoden.

    Using response As WebResponse = webReq.GetResponseAsync()
    
  2. GetResponseAsync returnerar en Task<TResult>. I det här fallet har aktivitetsreturvariabeln , TResulttypen WebResponse. Uppgiften är ett löfte om att skapa ett faktiskt WebResponse objekt efter att de begärda data har laddats ned och aktiviteten har körts till slutförande.

    Om du vill hämta WebResponse värdet från aktiviteten använder du en Await-operator för anropet till GetResponseAsync, som följande kod visar.

    Using response As WebResponse = Await webReq.GetResponseAsync()
    

    Operatorn Await pausar körningen av den aktuella metoden, GetURLContents, tills den inväntade aktiviteten har slutförts. Under tiden återgår kontrollen till anroparen för den aktuella metoden. I det här exemplet är GetURLContentsden aktuella metoden , och anroparen är SumPageSizes. När aktiviteten är klar skapas det utlovade WebResponse objektet som värdet för den inväntade aktiviteten och tilldelas till variabeln response.

    Föregående instruktion kan delas in i följande två instruktioner för att klargöra vad som händer.

    Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync()
    Using response As WebResponse = Await responseTask
    

    Anropet till webReq.GetResponseAsync returnerar en Task(Of WebResponse) eller Task<WebResponse>. Sedan tillämpas en Await operator på uppgiften för att hämta WebResponse värdet.

    Om din asynkrona metod har arbete att göra som inte beror på slutförandet av uppgiften, kan metoden fortsätta med det arbetet mellan dessa två instruktioner, efter anropet till async-metoden och innan await-operatorn tillämpas. Exempel finns i How to: Make Multiple Web Requests in Parallel by Using Async and Await (Visual Basic) and How to: Extend the Async Walkthrough by Using Task.WhenAll (Visual Basic).

  3. Eftersom du lade till operatorn Await i föregående steg uppstår ett kompilatorfel. Operatorn kan endast användas i metoder som är markerade med Async-modifieraren . Ignorera felet när du upprepar konverteringsstegen för att ersätta anropet till CopyTo med ett anrop till CopyToAsync.

    • Ändra namnet på den metod som anropas till CopyToAsync.

    • Metoden CopyTo eller CopyToAsync kopierar byte till argumentet , contentoch returnerar inte något meningsfullt värde. I den synkrona versionen är anropet till CopyTo en enkel instruktion som inte returnerar något värde. Den asynkrona versionen, CopyToAsync, returnerar en Task. Aktiviteten fungerar som "Task(void)" och gör det möjligt att vänta på metoden. Tillämpa Await eller await på anropet till CopyToAsync, som följande kod visar.

      Await responseStream.CopyToAsync(content)
      

      Föregående instruktion förkortar följande två kodrader.

      ' CopyToAsync returns a Task, not a Task<T>.
      Dim copyTask As Task = responseStream.CopyToAsync(content)
      
      ' When copyTask is completed, content contains a copy of
      ' responseStream.
      Await copyTask
      
  4. Allt som återstår att göra i GetURLContents är att justera metodsignaturen. Du kan endast använda operatorn Await i metoder som har markerats med Async-modifieraren . Lägg till modifieraren för att markera metoden som en asynkron metod, som följande kod visar.

    Private Async Function GetURLContents(url As String) As Byte()
    
  5. Returtypen för en asynkron metod kan bara vara Task, Task<TResult>. I Visual Basic måste metoden vara en Function som returnerar en Task eller en Task(Of T), eller så måste metoden vara .Sub Vanligtvis används en Sub metod endast i en asynkron händelsehanterare, där Sub krävs. I andra fall använder Task(T) du om den slutförda metoden har en Retur-instruktion som returnerar ett värde av typen T, och du använder Task om den slutförda metoden inte returnerar ett meningsfullt värde.

    Mer information finns i Async Return Types (Visual Basic).

    Metoden GetURLContents har en retursats och -instruktionen returnerar en bytematris. Därför är returtypen för asynkron version Task(T), där T är en bytematris. Gör följande ändringar i metodsignaturen:

    • Ändra returtypen till Task(Of Byte()).

    • Enligt konventionen har asynkrona metoder namn som slutar med "Async", så byt namn på metoden GetURLContentsAsync.

    Följande kod visar dessa ändringar.

    Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())
    

    Med dessa få ändringar slutförs konverteringen av GetURLContents till en asynkron metod.

Konvertera SumPageSizes till en asynkron metod

  1. Upprepa stegen från föregående procedur för SumPageSizes. Ändra först anropet till GetURLContents till ett asynkront anrop.

    • Ändra namnet på den metod som anropas från GetURLContents till GetURLContentsAsync, om du inte redan har gjort det.

    • Använd Await för uppgiften som GetURLContentsAsync returneras för att hämta värdet för bytematrisen.

    Följande kod visar dessa ändringar.

    Dim urlContents As Byte() = Await GetURLContentsAsync(url)
    

    Föregående tilldelning förkortar följande två kodrader.

    ' GetURLContentsAsync returns a task. At completion, the task
    ' produces a byte array.
    Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url)
    Dim urlContents As Byte() = Await getContentsTask
    
  2. Gör följande ändringar i metodens signatur:

    • Markera metoden med Async modifieraren.

    • Lägg till "Async" i metodnamnet.

    • Det finns ingen variabel för aktivitetsretur, T, den här gången eftersom SumPageSizesAsync inte returnerar ett värde för T. (Metoden har ingen Return instruktion.) Metoden måste dock returnera en Task för att vara väntande. Ändra därför metodtypen från Sub till Function. Returtypen för funktionen är Task.

    Följande kod visar dessa ändringar.

    Private Async Function SumPageSizesAsync() As Task
    

    Konverteringen av SumPageSizes till SumPageSizesAsync är klar.

Konvertera startButton_Click till en asynkron metod

  1. I händelsehanteraren ändrar du namnet på den anropade metoden från SumPageSizes till SumPageSizesAsync, om du inte redan har gjort det.

  2. Eftersom SumPageSizesAsync är en asynkron metod ändrar du koden i händelsehanteraren för att invänta resultatet.

    Anropet till SumPageSizesAsync speglar anropet till CopyToAsync i GetURLContentsAsync. Anropet returnerar en Task, inte en Task(T).

    Precis som i tidigare procedurer kan du konvertera anropet med hjälp av en instruktion eller två instruktioner. Följande kod visar dessa ändringar.

    ' One-step async call.
    Await SumPageSizesAsync()
    
    ' Two-step async call.
    Dim sumTask As Task = SumPageSizesAsync()
    Await sumTask
    
  3. Om du vill förhindra att åtgärden avslutas av misstag lägger du till följande -instruktion överst startButton_Click i för att inaktivera startknappen .

    ' Disable the button until the operation is complete.
    startButton.IsEnabled = False
    

    Du kan återaktivera knappen i slutet av händelsehanteraren.

    ' Reenable the button in case you want to run the operation again.
    startButton.IsEnabled = True
    

    Mer information om återaktivering finns i Hantera återaktivering i Async Apps (Visual Basic).

  4. Lägg slutligen till Async modifieraren i deklarationen så att händelsehanteraren kan vänta SumPagSizesAsyncpå .

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
    

    Vanligtvis ändras inte namnen på händelsehanterare. Returtypen ändras inte till Task eftersom händelsehanterare måste vara Sub procedurer i Visual Basic.

    Konverteringen av projektet från synkron till asynkron bearbetning är klar.

Testa den asynkrona lösningen

  1. Välj F5-tangenten för att köra programmet och välj sedan knappen Start .

  2. Utdata som liknar utdata från den synkrona lösningen bör visas. Observera dock följande skillnader.

    • Resultatet inträffar inte samtidigt när bearbetningen är klar. Båda programmen innehåller till exempel en rad i startButton_Click som rensar textrutan. Avsikten är att rensa textrutan mellan körningar om du väljer startknappen en andra gång, efter att en uppsättning resultat har dykt upp. I den synkrona versionen rensas textrutan precis innan antalet visas för andra gången, när nedladdningarna har slutförts och användargränssnittstråden är fri att utföra annat arbete. I den asynkrona versionen rensas textrutan direkt efter att du har valt knappen Start .

    • Viktigast av allt är att användargränssnittstråden inte blockeras under nedladdningarna. Du kan flytta eller ändra storlek på fönstret medan webbresurserna laddas ned, räknas och visas. Om någon av webbplatserna är långsam eller inte svarar kan du avbryta åtgärden genom att välja knappen Stäng (x i det röda fältet i det övre högra hörnet).

Ersätt metoden GetURLContentsAsync med en .NET Framework-metod

  1. .NET Framework innehåller många asynkrona metoder som du kan använda. En av dem, HttpClient.GetByteArrayAsync(String) metoden, gör precis vad du behöver för den här genomgången. Du kan använda den i stället för den GetURLContentsAsync metod som du skapade i en tidigare procedur.

    Det första steget är att skapa ett HttpClient objekt i SumPageSizesAsync -metoden. Lägg till följande deklaration i början av metoden.

    ' Declare an HttpClient object and increase the buffer size. The
    ' default buffer size is 65,536.
    Dim client As HttpClient =
        New HttpClient() With {.MaxResponseContentBufferSize = 1000000}
    
  2. Ersätt SumPageSizesAsync, anropet till metoden GetURLContentsAsync med ett anrop till HttpClient metoden.

    Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
  3. Ta bort eller kommentera ut den GetURLContentsAsync metod som du skrev.

  4. Välj F5-tangenten för att köra programmet och välj sedan knappen Start .

    Beteendet för den här versionen av projektet bör matcha det beteende som proceduren "Att testa den asynkrona lösningen" beskriver men med ännu mindre ansträngning från dig.

Exempel

Följande är det fullständiga exemplet på den konverterade asynkrona lösningen som använder den asynkrona GetURLContentsAsync metoden. Observera att den starkt liknar den ursprungliga synkrona lösningen.

' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http
Imports System.Net
Imports System.IO

Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click

        ' Disable the button until the operation is complete.
        startButton.IsEnabled = False

        resultsTextBox.Clear()

        '' One-step async call.
        Await SumPageSizesAsync()

        ' Two-step async call.
        'Dim sumTask As Task = SumPageSizesAsync()
        'Await sumTask

        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."

        ' Reenable the button in case you want to run the operation again.
        startButton.IsEnabled = True
    End Sub

    Private Async Function SumPageSizesAsync() As Task

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

        Dim total = 0
        For Each url In urlList
            Dim urlContents As Byte() = Await GetURLContentsAsync(url)

            ' The previous line abbreviates the following two assignment statements.

            '//<snippet21>
            ' GetURLContentsAsync returns a task. At completion, the task
            ' produces a byte array.
            'Dim getContentsTask As Task(Of Byte()) = GetURLContentsAsync(url)
            'Dim urlContents As Byte() = Await getContentsTask

            DisplayResults(url, urlContents)

            ' 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:  {0}" & vbCrLf, total)
    End Function

    Private Function SetUpURLList() As List(Of String)

        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/library/ff730837.aspx"
            }
        Return urls
    End Function

    Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())

        ' The downloaded resource ends up in the variable named content.
        Dim content = New MemoryStream()

        ' Initialize an HttpWebRequest for the current URL.
        Dim webReq = CType(WebRequest.Create(url), HttpWebRequest)

        ' Send the request to the Internet resource and wait for
        ' the response.
        Using response As WebResponse = Await webReq.GetResponseAsync()

            ' The previous statement abbreviates the following two statements.

            'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync()
            'Using response As WebResponse = Await responseTask

            ' Get the data stream that is associated with the specified URL.
            Using responseStream As Stream = response.GetResponseStream()
                ' Read the bytes in responseStream and copy them to content.
                Await responseStream.CopyToAsync(content)

                ' The previous statement abbreviates the following two statements.

                ' CopyToAsync returns a Task, not a Task<T>.
                'Dim copyTask As Task = responseStream.CopyToAsync(content)

                ' When copyTask is completed, content contains a copy of
                ' responseStream.
                'Await copyTask
            End Using
        End Using

        ' Return the result as a byte array.
        Return content.ToArray()
    End Function

    Private Sub DisplayResults(url As String, content As Byte())

        ' 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.
        Dim bytes = content.Length
        ' Strip off the "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

End Class

Följande kod innehåller det fullständiga exemplet på lösningen som använder HttpClient metoden . GetByteArrayAsync

' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http
Imports System.Net
Imports System.IO

Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click

        resultsTextBox.Clear()

        ' Disable the button until the operation is complete.
        startButton.IsEnabled = False

        ' One-step async call.
        Await SumPageSizesAsync()

        ' Two-step async call.
        'Dim sumTask As Task = SumPageSizesAsync()
        'Await sumTask

        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."

        ' Reenable the button in case you want to run the operation again.
        startButton.IsEnabled = True
    End Sub

    Private Async Function SumPageSizesAsync() As Task

        ' Declare an HttpClient object and increase the buffer size. The
        ' default buffer size is 65,536.
        Dim client As HttpClient =
            New HttpClient() With {.MaxResponseContentBufferSize = 1000000}

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

        Dim total = 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)

            ' The following two lines can replace the previous assignment statement.
            'Dim getContentsTask As Task(Of Byte()) = client.GetByteArrayAsync(url)
            'Dim urlContents As Byte() = Await getContentsTask

            DisplayResults(url, urlContents)

            ' 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:  {0}" & vbCrLf, total)
    End Function

    Private Function SetUpURLList() As List(Of String)

        Dim urls = New List(Of String) From
            {
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "https://msdn.microsoft.com",
                "https://msdn.microsoft.com/library/hh290136.aspx",
                "https://msdn.microsoft.com/library/ee256749.aspx",
                "https://msdn.microsoft.com/library/hh290138.aspx",
                "https://msdn.microsoft.com/library/hh290140.aspx",
                "https://msdn.microsoft.com/library/dd470362.aspx",
                "https://msdn.microsoft.com/library/aa578028.aspx",
                "https://msdn.microsoft.com/library/ms404677.aspx",
                "https://msdn.microsoft.com/library/ff730837.aspx"
            }
        Return urls
    End Function

    Private Sub DisplayResults(url As String, content As Byte())

        ' 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.
        Dim bytes = content.Length
        ' Strip off the "https://".
        Dim displayURL = url.Replace("https://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub

End Class

Se även