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 zur Async-Funktion 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 durcharbeiten oder das Beispiel aus dem .NET-Beispiel-Browser herunterladen. Der Beispielcode befindet sich im SerialAsyncExample-Projekt.
Im Verlauf dieser exemplarischen Vorgehensweise führen Sie folgende Aufgaben aus:
- Erstellen einer WPF-Anwendung
- Entwerfen eines einfachen WPF-MainWindows
- Hinzufügen eines Verweises
- Hinzufügen erforderlicher Imports-Anweisungen
- Erstellen einer synchronen Anwendung
- Testen der synchronen Lösung
- Konvertieren von „GetURLContents“ in eine asynchrone Methode
- Konvertieren von „SumPageSizes“ in eine asynchrone Methode
- Konvertieren von „startButton_Click“ in eine asynchrone Methode
- Testen der asynchronen Lösung
- Ersetzen der GetURLContentsAsync-Methode durch eine .NET Framework-Methode
Das vollständige asynchrone Beispiel finden Sie im Abschnitt Beispiel.
Voraussetzungen
Visual Studio 2012 oder höher muss auf dem Computer installiert sein. Weitere Informationen finden Sie bei auf der Seite Downloads von Visual Studio.
Erstellen einer WPF-Anwendung
Starten Sie Visual Studio.
Wählen Sie in der Menüleiste Datei, Neu, Projektaus.
Das Dialogfeld Neues Projekt wird angezeigt.
Wählen Sie im Bereich Installierte Vorlagen den Eintrag Visual Basic und dann in der Liste der Projekttypen WPF-Anwendung aus.
Geben Sie im Textfeld Name
AsyncExampleWPF
ein, und wählen Sie dann die Schaltfläche OK aus.Das neue Projekt wird im Projektmappen-Explorer angezeigt.
Entwerfen eines einfachen WPF-MainWindows
Wählen Sie im Visual Studio Code Editor die Registerkarte MainWindow.xaml aus.
Wenn das Fenster Toolbox nicht sichtbar ist, öffnen Sie das Menü Ansicht, und wählen Sie dann Toolbox aus.
Fügen Sie dem Fenster MainWindow ein Button-Steuerelement und ein TextBox-Steuerelement hinzu.
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.
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.
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
Markieren Sie im Projektmappen-Explorer den Namen des Projekts.
Wählen Sie in der Menüleiste die Optionen Projekt und Verweis hinzufügen aus.
Das Dialogfeld Verweis-Manager wird angezeigt.
Stellen Sie oben im Dialogfeld sicher, dass Ihr Projekt auf .NET Framework 4.5 oder höher abzielt.
Wählen Sie im Bereich Assemblys die Option Framework aus, wenn sie nicht bereits ausgewählt ist.
Aktivieren Sie in der Liste der Namen das Kontrollkästchen System.Net.Http.
Wählen Sie die Schaltfläche OK aus, um das Dialogfeld zu schließen.
Hinzufügen erforderlicher Imports-Anweisungen
Öffnen Sie im Projektmappen-Explorer das Kontextmenü für „MainWindow.xaml.vb“, und wählen Sie dann Code anzeigen aus.
Fügen Sie die folgenden
Imports
-Anweisungen am Anfang der Codedatei ein, wenn sie noch nicht vorhanden sind.Imports System.Net.Http Imports System.Net Imports System.IO
Erstellen einer synchronen Anwendung
Doppelklicken Sie im Entwurfsfenster „MainWindow.xaml“ auf die Schaltfläche Start, um den
startButton_Click
-Ereignishandler in „MainWindow.xaml.cs“ zu erstellen.Kopieren Sie in „MainWindow.xaml.vb“ den folgenden Code in den Textteil 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 zustartButton_Click
zurückgegeben wird.Der Code für die synchrone Lösung enthält die folgenden vier Methoden:
SumPageSizes
. Enthält eine Liste von Webseiten-URLs ausSetUpURLList
und ruft dannGetURLContents
undDisplayResults
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.DisplayResults
: Zeigt 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
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 weder verschieben, maximieren, minimieren noch 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
Für das Konvertieren der synchronen Projektmappe in eine asynchrone Projektmappe empfiehlt es sich, in
GetURLContents
zu beginnen, da die Aufrufe der HttpWebRequest.GetResponse-Methode und der Stream.CopyTo-Methode dort erfolgen, wo 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
vonGetResponse
zur asynchronen, aufgabenbasierten GetResponseAsync-Methode.Using response As WebResponse = webReq.GetResponseAsync()
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ächlichesWebResponse
-Objekt erstellt werden, nachdem die angeforderten Daten heruntergeladen und das Ausführen der Aufgabe abgeschlossen wurde.Wenden Sie analog zur Darstellung im folgenden Code zum Abrufen des
WebResponse
-Werts aus der Aufgabe einen Await-Operator für den Aufruf vonGetResponseAsync
an.Using response As WebResponse = Await webReq.GetResponseAsync()
Der
Await
-Operator hält die Ausführung der aktuellen MethodeGetURLContents
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 MethodeGetURLContents
, und der Aufrufer istSumPageSizes
. Wenn die Aufgabe abgeschlossen ist, wird das zugesicherteWebResponse
-Objekt als Wert der erwarteten Aufgabe erstellt und zur Variableresponse
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
wirdTask(Of WebResponse)
oderTask<WebResponse>
zurückgegeben. Anschließend wird einAwait
-Operator auf den Task angewendet, um denWebResponse
-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 Vorgehensweise: Paralleles Ausführen mehrerer Webanforderungen mithilfe von Async und Await (Visual Basic) und Vorgehensweise: Erweitern des der exemplarischen Vorgehensweise für Async durch Verwenden von Task.WhenAll (Visual Basic).
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 markiert sind. Ignorieren Sie den Fehler, während Sie die Konvertierungsschritte zum Ersetzen des Aufrufs vonCopyTo
mit einem Aufruf vonCopyToAsync
wiederholen.Ändern Sie den Namen der Methode, die für CopyToAsync aufgerufen wird.
Die Methode
CopyTo
oderCopyToAsync
kopiert Bytes zu ihrem Argumentcontent
und gibt keinen sinnvollen Wert zurück. In der synchronen Version ist der Aufruf vonCopyTo
eine einfache Anweisung, die keinen Wert zurückgibt. Die asynchrone VersionCopyToAsync
gibt ein Task zurück. Die Aufgabe funktioniert wie „Task(void)“ und ermöglicht, dass auf die Methode gewartet wird. Wenden SieAwait
oderawait
auf den Aufruf vonCopyToAsync
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
Somit muss nur noch die Methodensignatur in
GetURLContents
angepasst werden. DerAwait
-Operator kann nur in Methoden verwendet werden, die mit dem Async-Modifizierer markiert 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()
Der Rückgabetyp einer Async-Methode kann nur Task oder Task<TResult> sein. In Visual Basic muss die Methode eine
Function
sein, die eineTask
oder eineTask(Of T)
zurückgibt, oder die Methode muss einSub
sein. Für gewöhnlich wird eineSub
-Methode nur in einem asynchronen Ereignishandler verwendet, wennSub
erforderlich ist. In anderen Fällen verwenden SieTask(T)
, wenn die abgeschlossene Methode eine Return-Anweisung aufweist, die einen Wert vom Typ „T“ zurückgibt. Verwenden SieTask
, wenn die abgeschlossene Methode keinen sinnvollen Wert zurückgibt.Weitere Informationen finden Sie unter Asynchrone 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
Wiederholen Sie die Schritte des vorherigen Verfahrens für
SumPageSizes
. Ändern Sie zunächst den Aufruf vonGetURLContents
zu einem asynchronen Aufruf.Ändern Sie den Namen der Methode, die aufgerufen wird, von
GetURLContents
zuGetURLContentsAsync
, sofern Sie dies nicht bereits getan haben.Wenden Sie
Await
auf die Aufgabe an, die durchGetURLContentsAsync
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
Nehmen Sie folgende Änderungen in der Methodensignatur vor:
Markieren Sie die Methode mit dem Modifizierer
Async
.Fügen Sie dem Methodennamen „Async“ hinzu.
Es ist dieses Mal keine Taskrückgabevariable „T“ vorhanden, da
SumPageSizesAsync
keinen Wert für „T“ zurückgibt. (Die Methode weist keineReturn
-Anweisung auf.) Die Methode muss jedoch einenTask
zurückgeben, damit sie awaitable ist. Ändern Sie den Methodentyp daher vonSub
inFunction
. Der Rückgabetyp der Funktion lautetTask
.
Im folgenden Code sind diese Änderungen dargestellt.
Private Async Function SumPageSizesAsync() As Task
Die Konvertierung von
SumPageSizes
zuSumPageSizesAsync
ist abgeschlossen.
Konvertieren von „startButton_Click“ in eine asynchrone Methode
Ändern Sie im Ereignishandler den Namen der aufgerufenen Methode von
SumPageSizes
zuSumPageSizesAsync
, sofern Sie dies nicht bereits vorgenommen haben.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 vonCopyToAsync
inGetURLContentsAsync
wider. Der Aufruf gibt eineTask
und keineTask(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
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 zum erneuten Eintritt finden Sie unter Behandeln des erneuten Eintritts in asynchronen Apps (Visual Basic).
Fügen Sie der Deklaration abschließend den Modifizierer
Async
hinzu, sodass der Ereignishandler aufSumPagSizesAsync
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 in
Task
geändert, weil Ereignishandler in Visual BasicSub
-Prozeduren sein müssen.Die Konvertierung des Projekts von der synchronen zu asynchronen Verarbeitung ist abgeschlossen.
Testen der asynchronen Lösung
Drücken Sie die Taste F5, um das Programm auszuführen, und klicken Sie dann auf die Schaltfläche Starten .
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 Die die GetURLContentsAsync-Methode durch eine .NET Framework-Methode
.NET Framework bietet viele asynchrone Methoden, die Sie verwenden können. Eine von ihnen (die HttpClient.GetByteArrayAsync(String)-Methode) geht genau so vor, wie es in dieser exemplarischen Vorgehensweise erforderlich ist. 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}
SumPageSizesAsync
Ersetzen Sie in , den Aufruf derGetURLContentsAsync
Methode durch einen Aufruf derHttpClient
Methode.Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
Entfernen Sie die von Ihnen geschriebene
GetURLContentsAsync
-Methode, oder kommentieren Sie sie aus.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
Im Folgenden finden Sie ein vollständiges 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
- Async Sample: Webzugriff – Exemplarische Vorgehensweise (C# und Visual Basic)
- Await-Operator
- Asynchron
- Asynchrone Programmierung mit „Async“ und „Await“ (Visual Basic)
- Async Return Types (Visual Basic) (Asynchrone Rückgabetypen (Visual Basic))
- Task-based Asynchronous Programming (TAP) (Aufgabenbasiertes asynchrones Programmieren (TAP))
- How to: Extend the Async Walkthrough by Using Task.WhenAll (Visual Basic) (Gewusst wie: Erweitern der asynchronen exemplarischen Vorgehensweise mit Task.WhenAll (Visual Basic))
- How to: Make Multiple Web Requests in Parallel by Using Async and Await (Visual Basic) (Gewusst wie: Paralleles Erstellen mehrerer Webanforderungen mit Async und Await (Visual Basic))