Exemplarische Vorgehensweise: Zugreifen auf das Web mit Async und Await ( Visual Basic)

Sie können asynchrone Programme mit den Funktionen „Async/Await“ einfacher und intuitiver schreiben. Sie können asynchronen Code schreiben, der wie synchroner Code aussieht und veranlassen, dass der Compiler die komplizierten Rückruffunktionen und Fortsetzungen verarbeitet, die durch den asynchronen Code für gewöhnlich verursacht werden.

Weitere Informationen zum Async-Feature finden Sie unter Asynchrone Programmierung mit Async und Await (Visual Basic).

Diese exemplarische Vorgehensweise beginnt mit einer synchronen WPF-Anwendung (Windows Presentation Foundation), die die Anzahl der Bytes in einer Liste von Websites summiert. In der exemplarischen Vorgehensweise wird die Anwendung dann mithilfe der neuen Funktionen in eine asynchrone Lösung umgewandelt.

Sie können die Anwendungen entwickeln, indem Sie entweder die exemplarische Vorgehensweise ausführen oder das Beispiel aus dem .NET-Beispielbrowser herunterladen. Der Beispielcode befindet sich im SerialAsyncExample-Projekt .

Im Verlauf dieser exemplarischen Vorgehensweise führen Sie folgende Aufgaben aus:

Weitere Informationen finden Sie im Abschnitt "Beispiel" für das vollständige asynchrone Beispiel.

Voraussetzungen

Visual Studio 2012 oder höher muss auf dem Computer installiert sein. Weitere Informationen finden Sie auf der Seite " Visual Studio-Downloads ".

Erstellen einer WPF-Anwendung

  1. Starten Sie Visual Studio.

  2. Wählen Sie in der Menüleiste Datei, Neu, Projektaus.

    Das Dialogfeld Neues Projekt wird angezeigt.

  3. Wählen Sie im Bereich "Installierte Vorlagen " Visual Basic aus, und wählen Sie dann "WPF-Anwendung " aus der Liste der Projekttypen aus.

  4. Geben Sie im Textfeld NameAsyncExampleWPF ein, und wählen Sie dann die Schaltfläche OK aus.

    Das neue Projekt wird im Projektmappen-Explorer angezeigt.

Entwerfen eines einfachen WPF-MainWindows

  1. Wählen Sie im Visual Studio Code Editor die Registerkarte MainWindow.xaml aus.

  2. Wenn das Toolboxfenster nicht sichtbar ist, öffnen Sie das Menü "Ansicht ", und wählen Sie dann " Toolbox" aus.

  3. Fügen Sie dem Fenster MainWindow ein Button-Steuerelement und ein TextBox-Steuerelement hinzu.

  4. Markieren Sie das TextBox-Steuerelement, und legen Sie im Fenster Eigenschaften die folgenden Werte fest:

    • Legen Sie die Eigenschaft Nameauf resultsTextBox fest.

    • Legen Sie die Eigenschaft Height auf „250“ fest.

    • Legen Sie die Eigenschaft Width auf „500“ fest.

    • Geben Sie auf der Registerkarte Text eine Festbreitenschriftart wie Lucida Console oder Global Monospace an.

  5. Markieren Sie das Button-Steuerelement, und legen Sie im Fenster Eigenschaften die folgenden Werte fest:

    • Legen Sie die Eigenschaft Name auf startButton fest.

    • Ändern Sie den Wert der Eigenschaft Content von Button zu Start.

  6. Positionieren Sie das Textfeld und die Schaltfläche so, dass beide im Fenster MainWindow angezeigt werden.

    Weitere Informationen über den WPF-XAML-Designer finden Sie unter Erstellen einer Benutzeroberfläche mit dem XAML-Designer.

Hinzufügen eines Verweises

  1. Markieren Sie im Projektmappen-Explorer den Namen des Projekts.

  2. Wählen Sie in der Menüleiste die Optionen Projekt und Verweis hinzufügen aus.

    Das Dialogfeld Verweis-Manager wird angezeigt.

  3. Stellen Sie oben im Dialogfeld sicher, dass Ihr Projekt auf .NET Framework 4.5 oder höher abzielt.

  4. Wählen Sie im Bereich Assemblys die Option Framework aus, wenn sie nicht bereits ausgewählt ist.

  5. Aktivieren Sie in der Liste der Namen das Kontrollkästchen System.Net.Http.

  6. Wählen Sie die Schaltfläche OK aus, um das Dialogfeld zu schließen.

Hinzufügen erforderlicher Imports-Anweisungen

  1. Öffnen Sie in Projektmappen-Explorer das Kontextmenü für "MainWindow.xaml.vb", und wählen Sie dann "Code anzeigen" aus.

  2. Fügen Sie oben in der Codedatei die folgenden Imports Anweisungen hinzu, wenn sie noch nicht vorhanden sind.

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

Erstellen einer synchronen Anwendung

  1. Doppelklicken Sie im Entwurfsfenster auf "MainWindow.xaml" auf die Schaltfläche " Start ", um den startButton_Click Ereignishandler in "MainWindow.xaml.vb" zu erstellen.

  2. Kopieren Sie in "MainWindow.xaml.vb" den folgenden Code in den Textkörper von startButton_Click:

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

    Der Code ruft die Methode SumPageSizes auf, die die Anwendung steuert und zeigt eine Meldung an, wenn das Steuerelement zu startButton_Click zurückgegeben wird.

  3. Der Code für die synchrone Lösung enthält die folgenden vier Methoden:

    • SumPageSizes. Enthält eine Liste von Webseiten-URLs aus SetUpURLList und ruft dann GetURLContents und DisplayResults auf, um jede URL zu verarbeiten.

    • SetUpURLList. Erstellt und gibt eine Liste der Webadressen zurück.

    • GetURLContents. Lädt Inhalte jeder Website herunter und gibt die Inhalte als ein Bytearray zurück.

    • DisplayResultszeigt die Anzahl der Bytes im Bytearray für jede URL an.

    Kopieren Sie die folgenden vier Methoden, und fügen Sie sie dann unter dem startButton_Click Ereignishandler in MainWindow.xaml.vb ein:

    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
    

Testen der synchronen Lösung

  1. Drücken Sie die Taste F5, um das Programm auszuführen, und klicken Sie dann auf die Schaltfläche Starten .

    Die Ausgabe sollte der folgenden Liste ähnlich sein:

    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.
    

    Beachten Sie, dass es ein paar Sekunden dauert, bis die Zahlen angezeigt werden. Während dieser Zeit ist der Benutzeroberflächenthread blockiert, während auf das Herunterladen von angeforderten Ressourcen gewartet wird. Daher können Sie das Anzeigefenster nicht verschieben, maximieren, minimieren oder sogar schließen, nachdem Sie die Schaltfläche " Start " ausgewählt haben. Diese Bemühungen sind nicht erfolgreich, bis der Bytezähler angezeigt wird. Wenn eine Website nicht antwortet, erhalten Sie keinen Hinweis darüber, welche Site fehlerhaft ist. Es ist sogar schwierig, mit dem Warten aufzuhören und das Programm zu schließen.

Konvertieren von „GetURLContents“ in eine asynchrone Methode

  1. Um die synchrone Lösung in eine asynchrone Lösung zu konvertieren, ist GetURLContents der beste Ausgangspunkt, da die Aufrufe der HttpWebRequest.GetResponse Methode und auf die Methode an der Stelle liegen, an der Stream.CopyTo die Anwendung auf das Web zugreift. .NET Framework erleichtert die Konvertierung, indem asynchrone Versionen beider Methoden bereitgestellt werden.

    Weitere Informationen über die in GetURLContents verwendeten Methoden finden Sie unter WebRequest.

    Hinweis

    Beim Befolgen der Schritte in dieser exemplarischen Vorgehensweise treten verschiedene Compilerfehler auf. Sie können diese ignorieren und mit der exemplarischen Vorgehensweise fortfahren.

    Ändern Sie die Methode, die aufgerufen wird, in der dritten Zeile von GetURLContents von GetResponse zur asynchronen, aufgabenbasierten GetResponseAsync-Methode.

    Using response As WebResponse = webReq.GetResponseAsync()
    
  2. GetResponseAsync gibt einen Wert vom Typ Task<TResult> zurück. In diesem Fall weist die Aufgabenrückgabevariable, TResult, den Typ WebResponse auf. Mit dieser Aufgabe soll ein tatsächliches WebResponse-Objekt erstellt werden, nachdem die angeforderten Daten heruntergeladen und das Ausführen der Aufgabe abgeschlossen wurde.

    Um den Wert aus der Aufgabe abzurufen, wenden Sie einen WebResponseAwait-Operator auf den Aufruf GetResponseAsyncan, wie der folgende Code zeigt.

    Using response As WebResponse = Await webReq.GetResponseAsync()
    

    Der Await-Operator hält die Ausführung der aktuellen Methode GetURLContents an, bis die Aufgabe abgeschlossen ist. In der Zwischenzeit kehrt die Steuerung zum Aufrufer der aktuellen Methode zurück. In diesem Beispiel lautet die aktuelle Methode GetURLContents, und der Aufrufer ist SumPageSizes. Wenn die Aufgabe abgeschlossen ist, wird das zugesicherte WebResponse-Objekt als Wert der erwarteten Aufgabe erstellt und zur Variable response zugewiesen.

    Die vorherige Anweisung kann in die folgenden zwei Anweisungen getrennt werden, um zu verdeutlichen, was geschieht.

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

    Durch den Aufruf von webReq.GetResponseAsync wird Task(Of WebResponse) oder Task<WebResponse> zurückgegeben. Anschließend wird ein Await Operator auf die Aufgabe angewendet, um den WebResponse Wert abzurufen.

    Wenn Ihre asynchrone Methode Aktionen vornehmen muss, die nicht von der Fertigstellung der Aufgabe abhängen, kann die Methode diese Aktionen zwischen zwei Anweisungen fortsetzen, und zwar nach dem Aufruf der asynchronen Methode und vor dem Anwenden des await-Operators. Beispiele finden Sie unter How to: Make Multiple Web Requests in parallel by Using Async and Await (Visual Basic) andHow to: Extend the Async Walkthrough by Using Task.WhenAll (Visual Basic).

  3. Da Sie den Operator Await im vorherigen Schritt hinzugefügt haben, tritt ein Compilerfehler auf. Der Operator kann nur in Methoden verwendet werden, die mit dem Async-Modifizierer gekennzeichnet sind. Ignorieren Sie den Fehler, während Sie die Konvertierungsschritte zum Ersetzen des Aufrufs von CopyTo mit einem Aufruf von CopyToAsync wiederholen.

    • Ändern Sie den Namen der Methode, die für CopyToAsync aufgerufen wird.

    • Die Methode CopyTo oder CopyToAsync kopiert Bytes zu ihrem Argument content und gibt keinen sinnvollen Wert zurück. In der synchronen Version ist der Aufruf von CopyTo eine einfache Anweisung, die keinen Wert zurückgibt. Die asynchrone Version CopyToAsync gibt ein Task zurück. Die Aufgabe funktioniert wie „Task(void)“ und ermöglicht, dass auf die Methode gewartet wird. Wenden Sie Await oder await auf den Aufruf von CopyToAsync an, wie dies im folgenden Code gezeigt wird.

      Await responseStream.CopyToAsync(content)
      

      Die vorherige Anweisung kürzt die folgenden zwei Codezeilen.

      ' 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. Somit muss nur noch die Methodensignatur in GetURLContents angepasst werden. Sie können den Await Operator nur in Methoden verwenden, die mit dem Async-Modifizierer gekennzeichnet sind. Fügen Sie den Modifizierer hinzu, um die Methode als eine async-Methode zu markieren, wie im folgenden Code gezeigt wird.

    Private Async Function GetURLContents(url As String) As Byte()
    
  5. Der Rückgabetyp einer asynchronen Methode kann nur Tasksein , Task<TResult>. In Visual Basic muss die Methode eine Function sein, die eine Task oder eine Task(Of T) zurückgibt, oder die Methode muss ein Sub sein. Normalerweise wird eine Sub Methode nur in einem asynchronen Ereignishandler verwendet, wo Sub erforderlich. In anderen Fällen verwenden Sie, wenn die abgeschlossene Methode über eine Return-Anweisung verfügt, die einen Wert vom Typ T zurückgibt, und Sie verwenden TaskTask(T), wenn die abgeschlossene Methode keinen aussagekräftigen Wert zurückgibt.

    Weitere Informationen finden Sie unter Async-Rückgabetypen (Visual Basic).

    Die Methode GetURLContents verfügt über eine return-Anweisung, und die Anweisung gibt ein Bytearray zurück. Daher ist der Rückgabetyp der der asynchronen Version „Task(T)“, wobei „T“ ein Bytearray ist. Nehmen Sie folgende Änderungen in der Methodensignatur vor:

    • Ändern Sie den Rückgabetyp zu Task(Of Byte()).

    • Asynchrone Methoden verfügen gemäß der Konvention über Namen, die auf „Async“ enden. Benennen Sie also die Methode GetURLContentsAsync um.

    Im folgenden Code sind diese Änderungen dargestellt.

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

    Mit diesen wenigen Änderungen ist die Konvertierung von GetURLContents zu einer asynchronen Methode abgeschlossen.

Konvertieren von „SumPageSizes“ in eine asynchrone Methode

  1. Wiederholen Sie die Schritte des vorherigen Verfahrens für SumPageSizes. Ändern Sie zunächst den Aufruf von GetURLContents zu einem asynchronen Aufruf.

    • Ändern Sie den Namen der Methode, die aufgerufen wird, von GetURLContents zu GetURLContentsAsync, sofern Sie dies nicht bereits getan haben.

    • Wenden Sie Await auf die Aufgabe an, die durch GetURLContentsAsync zurückgegeben wird, um den Bytearraywert abzurufen.

    Im folgenden Code sind diese Änderungen dargestellt.

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

    Die vorherige Zuweisung kürzt die folgenden zwei Codezeilen.

    ' 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. Nehmen Sie folgende Änderungen in der Methodensignatur vor:

    • Markieren Sie die Methode mit dem Modifizierer Async.

    • Fügen Sie dem Methodennamen „Async“ hinzu.

    • Es gibt keine Task-Rückgabevariable, T, dieses Mal, da SumPageSizesAsync kein Wert für T zurückgegeben wird. (Die Methode hat keine Return Anweisung.) Die Methode muss jedoch einen Task zu erwartenden Wert zurückgeben. Ändern Sie daher den Methodentyp von Sub zu Function. Der Rückgabetyp der Funktion lautet Task.

    Im folgenden Code sind diese Änderungen dargestellt.

    Private Async Function SumPageSizesAsync() As Task
    

    Die Konvertierung von SumPageSizes zu SumPageSizesAsync ist abgeschlossen.

Konvertieren von „startButton_Click“ in eine asynchrone Methode

  1. Ändern Sie im Ereignishandler den Namen der aufgerufenen Methode von SumPageSizes zu SumPageSizesAsync, sofern Sie dies nicht bereits vorgenommen haben.

  2. Da es sich bei SumPageSizesAsync um eine asynchrone Methode handelt, ändern Sie den Code im Ereignishandler, um auf das Ergebnis zu warten.

    Der Aufruf von SumPageSizesAsync spiegelt den Aufruf von CopyToAsync in GetURLContentsAsync wider. Der Aufruf gibt eine Task und keine Task(T) zurück.

    Analog zu den vorherigen Vorgehensweisen können Sie den Aufruf mithilfe von einer oder zwei Anweisungen konvertieren. Im folgenden Code sind diese Änderungen dargestellt.

    ' One-step async call.
    Await SumPageSizesAsync()
    
    ' Two-step async call.
    Dim sumTask As Task = SumPageSizesAsync()
    Await sumTask
    
  3. Um den versehentlichen Neustart des Vorgangs zu verhindern, fügen Sie oben in startButton_Click die folgende Anweisung ein, um die Schaltfläche Start zu deaktivieren.

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

    Sie können die Schaltfläche am Ende des Ereignishandlers wieder aktivieren.

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

    Weitere Informationen zur Reentranz finden Sie unter Handling Reentrancy in Async Apps (Visual Basic).

  4. Fügen Sie der Deklaration abschließend den Modifizierer Async hinzu, sodass der Ereignishandler auf SumPagSizesAsync warten kann.

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

    In der Regel werden die Namen der Ereignishandler nicht geändert. Der Rückgabetyp wird nicht geändert Task , da Ereignishandler Prozeduren in Visual Basic sein müssen Sub .

    Die Konvertierung des Projekts von der synchronen zu asynchronen Verarbeitung ist abgeschlossen.

Testen der asynchronen Lösung

  1. Drücken Sie die Taste F5, um das Programm auszuführen, und klicken Sie dann auf die Schaltfläche Starten .

  2. Es sollte eine Ausgabe angezeigt werden, die der Ausgabe der synchronen Lösung gleicht. Folgende Unterschiede sind jedoch zu berücksichtigen.

    • Die Ergebnisse treten nicht alle gleichzeitig auf, nachdem die Verarbeitung abgeschlossen wurde. Beispielsweise enthalten beide Programme eine Zeile in startButton_Click, die das Textfeld löscht. Es ist vorgesehen, das Textfeld zwischen zwei Ausführungen zu löschen, wenn Sie die Schaltfläche Start ein zweites Mal auswählen, nachdem ein Ergebnissatz angezeigt wurde. In der synchronen Version wird das Textfeld unmittelbar vor der zweiten Anzeige des Zählers gelöscht, wenn die Downloads abgeschlossen sind und der UI-Thread für die Verarbeitung anderer Aktionen frei ist. In der asynchronen Version wird das Textfeld unmittelbar gelöscht, nachdem Sie die Schaltfläche Start ausgewählt haben.

    • Das Wichtigste ist jedoch, dass der UI-Thread nicht blockiert wird, während Downloads vorgenommen werden. Sie können das Fenster verschieben oder dessen Größe anpassen, während die Webressourcen heruntergeladen, gezählt und angezeigt werden. Wenn eine der Websites langsam ist oder nicht antwortet, können Sie den Vorgang abbrechen, indem Sie die Schaltfläche Schließen (das x im roten Feld in der oberen rechten Ecke) auswählen.

Ersetzen Sie die GetURLContentsAsync-Methode durch eine .NET Framework-Methode

  1. Die .NET Framework bietet viele asynchrone Methoden, die Sie verwenden können. Eine davon, die HttpClient.GetByteArrayAsync(String) Methode, führt genau das aus, was Sie für diese exemplarische Vorgehensweise benötigen. Sie können sie anstelle der GetURLContentsAsync-Methode verwenden, die Sie in einer vorherigen Vorgehensweise erstellt haben.

    Der erste Schritt besteht darin, ein HttpClient Objekt in der SumPageSizesAsync Methode zu erstellen. Fügen Sie am Anfang der Methode die folgende Deklaration hinzu.

    ' 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. Ersetzen Sie in SumPageSizesAsync, den Aufruf zu Ihrer GetURLContentsAsync-Methode durch einen Aufruf zur Methode HttpClient.

    Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
    
  3. Entfernen Sie die von Ihnen geschriebene GetURLContentsAsync-Methode, oder kommentieren Sie sie aus.

  4. Drücken Sie die Taste F5, um das Programm auszuführen, und klicken Sie dann auf die Schaltfläche Starten .

    Das Verhalten dieser Version des Projekts sollte mit dem Verhalten übereinstimmen, das in der Vorgehensweise „So testen Sie die asynchrone Lösung“ beschrieben wird, es sollte aber weniger Aufwand Ihrerseits nötig sein.

Beispiel

Nachfolgend sehen Sie das vollständige Beispiel für die konvertierte asynchrone Lösung, die die asynchrone GetURLContentsAsync Methode verwendet. Beachten Sie, dass sie der ursprünglichen synchronen Lösung sehr stark ähnelt.

' 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

Der folgende Code umfasst das vollständige Beispiel der Lösung, die die HttpClient-Methode GetByteArrayAsync verwendet.

' 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

Siehe auch