Exemplarische Vorgehensweise: Zugreifen auf das Web mit Async und Await (C# und Visual Basic)
Sie können asynchrone Programme einfach und intuitiv schreiben, indem Sie Funktionen verwenden, die in Visual Studio 2012 eingegeben werden.Sie können asynchronen Code schreiben, das das synchroner Code und den Compiler die schwierigen Rückruffunktionen und die Fortsetzungen behandeln können, die asynchronen Code normalerweise zur Folge hat.
Weitere Informationen über die asynchrone Funktion, finden Sie unter Asynchrone Programmierung mit Async und Await (C# und Visual Basic).
startet diesen exemplarischen Vorgehensweise mit einer synchronen WPF- (Windows Presentation Foundation), die die Anzahl der Bytes in einer Liste von Websites summiert.Die exemplarische Vorgehensweise konvertiert dann die Anwendung in einer asynchronen Projektmappe, indem sie die neuen Funktionen verwendet.
Wenn Sie nicht die Anwendungen selbst erstellen möchten, können Sie "asynchrones Beispiel herunterladen: Auf die Internet-exemplarischeVorgehensweise (C# und Visual Basic)" zugreifen Entwickler-Codebeispiele.
In dieser exemplarischen Vorgehensweise führen Sie folgende Aufgaben aus:
Create a WPF application.
Design a simple WPF MainWindow window.
Add a reference.
Add Imports statements or using directives.
Create a synchronous solution.
Test the synchronous solution.
Convert GetURLContents to an asynchronous method.
Convert SumPageSizes to an asynchronous method.
Convert startButton_Click to an asynchronous method.
Test the asynchronous solution.
Replace GetURLContentsAsync with a .NET Framework method.
Complete Code Examples from the Walkthrough
Vorbereitungsmaßnahmen
Visual Studio 2012 muss auf dem Computer installiert werden.Weitere Informationen finden Sie auf der Microsoft-Website.
So erstellen Sie eine WPF-Anwendung
Starten Sie Visual Studio.
Wählen Sie in der Menüleiste Datei, Neu, Projekt aus.
Das Dialogfeld Neues Projekt wird angezeigt.
Im Bereich Installierte Vorlagen wählen Sie Visual Basic oder Visual C# aus, und wählen Sie dann WPF-Anwendung aus der Liste der - Projekttypen aus.
Im Name Textfeld geben Sie AsyncExampleWPF ein und klicken Sie dann auf die Schaltfläche OK aus.
Das neue Projekt wird im Projektmappen-Explorer angezeigt.
So fügen Sie ein einfaches WPF MainWindow entwerfen
In Visual Studio MainWindow.xaml wählen Sie die Registerkarte aus.
Wenn das Werkzeugkasten nicht sichtbar ist, Ansicht öffnen Sie das Menü, und wählen Sie dann Werkzeugkasten aus.
Fügen Sie ein - Steuerelement und ein SharePoint aktivierenTextBox-Steuerelement dem Fenster MainWindow hinzu.
Markieren Sie das Steuerelement TextBox und, Eigenschaften im Fenster hervorgehoben, legen Sie die folgenden Werte fest:
Legen Sie die - Eigenschaft auf NameresultsTextBox fest.
Legen Sie die Eigenschaft Höhe auf 250 fest.
Legen Sie die Eigenschaft Breite auf 500 fest.
Klicken Sie auf der Registerkarte Text eine monospaced-Schriftart, wie Lucida-Konsole an, oder global Monospace.
Markieren Sie das Steuerelement SharePoint aktivieren und, Eigenschaften im Fenster hervorgehoben, legen Sie die folgenden Werte fest:
Legen Sie die - Eigenschaft auf NameStartknopf fest.
Ändern Sie den Wert der - Eigenschaft Inhalt von SharePoint aktivieren zu Start.
Positionieren Sie das Textfeld und die Schaltfläche, damit beide MainWindow im Fenster angezeigt werden.
Weitere Informationen zu den WPF-XAML Designer, finden Sie unter Erstellen einer Benutzeroberfläche mit dem XAML-Designer.
So fügen Sie einen Verweis hinzu
In Projektmappen-Explorer markieren Sie den Namen des Projekts hervor.
Klicken Sie auf der Menüleiste wählen Sie Projekt, Verweis hinzufügen aus.
Das Dialogfeld wird angezeigt. Verweis-Manager
am oberen Rand des Dialogfelds sicher, dass das Projekt auf .NET Framework 4.5 abzielt.
Im Bereich Assemblys wählen Sie Framework aus, wenn nicht bereits ausgewählt ist.
In der Namensliste System.Net.Http aktivieren Sie das Kontrollkästchen.
Wählen Sie die Schaltfläche OK, um das Dialogfeld zu schließen.
So fügen Sie erforderliche Imports-Anweisungen oder using-Direktiven hinzu
In Projektmappen-Explorer öffnen Sie das Kontextmenü für MainWindow.xaml.cs oder MainWindow.xaml.vb, und wählen Sie dann Code anzeigen aus.
Fügen Sie die folgenden Imports-Anweisungen (Visual Basic) oder using eine - Direktive (C#) am Anfang der Codedatei hinzu, wenn sie noch nicht vorhanden sind.
Imports System.Net.Http Imports System.Net Imports System.IO
using System.Net.Http; using System.Net; using System.IO;
Um eine synchrone Anwendung erstellen
Im Entwurfsfenster doppelklicken MainWindow.xaml, Start auf die Schaltfläche, um den startButton_Click-Ereignishandler in "MainWindow.xaml.vb" oder zu erstellen.Als Alternative, die Schaltfläche Start markieren, aktivieren Sie das Ereignishandler für die ausgewählten Elemente Symbol im Eigenschaften aus, und geben Sie dann startButton_ClickKlicken im Textfeld ein.
Klicken Sie in "MainWindow.xaml.vb" oder kopieren Sie den folgenden Code in den Text von startButton_Click.
resultsTextBox.Clear() SumPageSizes() resultsTextBox.Text &= vbCrLf & "Control returned to startButton_Click."
resultsTextBox.Clear(); SumPageSizes(); resultsTextBox.Text += "\r\nControl returned to startButton_Click.";
Der Code ruft die - Methode auf, die die Anwendung, SumPageSizes steuert und eine Meldung angezeigt, wenn die Steuerung an startButton_Click zurückgibt.
Der Code für die synchrone Projektmappe enthält die folgenden vier Methoden:
SumPageSizes, die eine Liste der Webseite URL von SetUpURLList und dann abruft, GetURLContents und DisplayResults, um jede URL zu verarbeiten aufruft.
SetUpURLList, das eine Liste von den Webadressen macht und zurückgibt.
GetURLContents, das den Inhalt jeder Website Herunterladen und den Inhalt als Bytearray zurückgibt.
DisplayResults, das die Anzahl von Bytes im Bytearray für jede URL anzeigt.
Kopieren Sie die folgenden vier Methoden, und fügen Sie sie unter den startButton_Click-Ereignishandler in "MainWindow.xaml.vb" oder 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/en-us/library/hh290136.aspx", "https://msdn.microsoft.com/en-us/library/ee256749.aspx", "https://msdn.microsoft.com/en-us/library/hh290138.aspx", "https://msdn.microsoft.com/en-us/library/hh290140.aspx", "https://msdn.microsoft.com/en-us/library/dd470362.aspx", "https://msdn.microsoft.com/en-us/library/aa578028.aspx", "https://msdn.microsoft.com/en-us/library/ms404677.aspx", "https://msdn.microsoft.com/en-us/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. 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 "http://". Dim displayURL = url.Replace("http://", "") resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes) End Sub
private void SumPageSizes() { // Make a list of web addresses. List<string> urlList = SetUpURLList(); var total = 0; foreach (var url in urlList) { // GetURLContents returns the contents of url as a byte array. byte[] urlContents = GetURLContents(url); DisplayResults(url, urlContents); // Update the total. total += urlContents.Length; } // Display the total count for all of the web addresses. resultsTextBox.Text += string.Format("\r\n\r\nTotal bytes returned: {0}\r\n", total); } private List<string> SetUpURLList() { var urls = new List<string> { "https://msdn.microsoft.com/library/windows/apps/br211380.aspx", "https://msdn.microsoft.com", "https://msdn.microsoft.com/en-us/library/hh290136.aspx", "https://msdn.microsoft.com/en-us/library/ee256749.aspx", "https://msdn.microsoft.com/en-us/library/hh290138.aspx", "https://msdn.microsoft.com/en-us/library/hh290140.aspx", "https://msdn.microsoft.com/en-us/library/dd470362.aspx", "https://msdn.microsoft.com/en-us/library/aa578028.aspx", "https://msdn.microsoft.com/en-us/library/ms404677.aspx", "https://msdn.microsoft.com/en-us/library/ff730837.aspx" }; return urls; } private byte[] GetURLContents(string url) { // The downloaded resource ends up in the variable named content. var content = new MemoryStream(); // Initialize an HttpWebRequest for the current URL. var webReq = (HttpWebRequest)WebRequest.Create(url); // Send the request to the Internet resource and wait for // the response. using (WebResponse response = webReq.GetResponse()) { // Get the data stream that is associated with the specified URL. using (Stream responseStream = response.GetResponseStream()) { // Read the bytes in responseStream and copy them to content. responseStream.CopyTo(content); } } // Return the result as a byte array. return content.ToArray(); } private void DisplayResults(string url, byte[] content) { // 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. var bytes = content.Length; // Strip off the "http://". var displayURL = url.Replace("http://", ""); resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes); }
Um die synchrone Projektmappe testen
Wählen Sie die F5-TASTE, um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start aus.
Geben Sie aus, das der folgenden Liste werden sollte ähnelt.
msdn.microsoft.com/library/windows/apps/br211380.aspx 383832 msdn.microsoft.com 33964 msdn.microsoft.com/en-us/library/hh290136.aspx 225793 msdn.microsoft.com/en-us/library/ee256749.aspx 143577 msdn.microsoft.com/en-us/library/hh290138.aspx 237372 msdn.microsoft.com/en-us/library/hh290140.aspx 128279 msdn.microsoft.com/en-us/library/dd470362.aspx 157649 msdn.microsoft.com/en-us/library/aa578028.aspx 204457 msdn.microsoft.com/en-us/library/ms404677.aspx 176405 msdn.microsoft.com/en-us/library/ff730837.aspx 143474 Total bytes returned: 1834802 Control returned to startButton_Click.
Beachten Sie, dass einige Sekunden benötigt, um die Anzahl anzuzeigen.Während dieser Zeit wird der UI-Thread blockiert, während er auf angeforderte Ressourcen wartet, um herunterzuladen.Daher können Sie das Fenster nicht verschieben, maximieren, minimieren oder sogar schließen, nachdem Sie die Schaltfläche Start auswählen.Diese Schritte werden bis zu den Byteanzahlanfang werden aus.Wenn eine Website nicht reagiert, haben Sie keinen Hinweis darauf, von dem Site fehlgeschlagen ist.Es ist schwierig sogar warten beendet und das Programm zu schließen.
Vergleichen Sie dieses Verhalten zu Beispiel zu einer asynchronen Projektmappe.
So GetURLContents zu einer asynchronen Methode konvertieren
Um die synchrone Projektmappe zu einer asynchronen Projektmappe konvertieren, wird der beste Ort, um den zu starten GetURLContents in, da die Aufrufe an die - Methode HttpWebRequestGetResponse und zur Stream-Methode CopyTo sind, wo die Anwendung auf das Internet zugreift.. .NET Framework macht die Konvertierung einfach, indem asynchrone Versionen beider Methoden angibt.
Weitere Informationen über die Methoden, die in GetURLContents verwendet werden, finden Sie unter WebRequest.
Hinweis Wenn Sie die Schritte in dieser exemplarischen Vorgehensweise folgen, werden einige Compilerfehler.Sie können sie ignorieren und mit der exemplarischen Vorgehensweise fortfahren.
Ändern Sie die - Methode, die in der dritten Zeile von GetURLContents von GetResponse zur asynchronen, aufgabenbasierte GetResponseAsync-Methode aufgerufen wird.
Using response As WebResponse = webReq.GetResponseAsync()
using (WebResponse response = webReq.GetResponseAsync())
GetResponseAsync gibt Task<TResult> zurück.In diesem Fall hat die Aufgabenrückgabevariable, TResult, Typ WebResponse.Die Aufgabe ist eine Zusicherung, eine tatsächliche WebResponse-Objekt zu erzeugen, nachdem die angeforderten Daten heruntergeladen wurden und die Aufgabe abgeschlossen ausgeführt wurde.
Um den WebResponse-Wert von der Aufgabe abzurufen, wenden Sie einen Operator Rechnen Sie (Visual Basic) oder Sie erwarten (C#) zum Aufruf von GetResponseAsync, wie im folgenden Code veranschaulicht.
Using response As WebResponse = Await webReq.GetResponseAsync()
using (WebResponse response = await webReq.GetResponseAsync())
Der Erwartungsoperator enthält die Ausführung der aktuellen Methode, GetURLContents an, bis die erwartete Aufgabe ist abgeschlossen.Mittlerweile kehrt die Steuerung an den Aufrufer der aktuellen Methode zurück.In diesem Beispiel ist die aktuelle Methode GetURLContents, und der Aufrufer ist SumPageSizes.Wenn die Aufgabe beendet ist, wird das viel versprechende WebResponse-Objekt als Wert der erwarteten Aufgabe erzeugt und variablen response zugewiesen.
Die vorherige - Anweisung kann in die folgenden beiden - Anweisungen getrennt werden, um zu erläutern, was geschieht.
'Dim responseTask As Task(Of WebResponse) = webReq.GetResponseAsync() 'Using response As WebResponse = Await responseTask
//Task<WebResponse> responseTask = webReq.GetResponseAsync(); //using (WebResponse response = await responseTask)
Der Aufruf webReq.GetResponseAsync gibt Task(Of WebResponse) oder Task<WebResponse> zurück.Anschließend wird ein Erwartungsoperator Aufgabe, den Wert abzurufen WebResponse angewendet.
Wenn die asynchrone Methode die Arbeit hat, auszuführen, die nicht vom Abschluss der Aufgabe abhängig ist, kann die - Methode mit dieser Arbeit zwischen diesen beiden Anweisungen, nach dem Aufruf der asynchronen Methode fortfahren und vor der Erwartungsoperator angewendet wird.Beispiele zu diesem Thema finden Sie unter Gewusst wie: Paralleles Erstellen mehrerer Webanforderungen (C# und Visual Basic) und Gewusst wie: Erweitern der exemplarischen Vorgehensweise mit Task.WhenAll (C# und Visual Basic).
Da Sie den Await oder await-Operator im vorherigen Schritt hinzugefügt haben, tritt ein Compilerfehler auf.Der Operator kann nur in Methoden verwendet werden, die mit dem - Modifizierer Asynchrone (Visual Basic) oder asynchron (C#) gekennzeichnet.Ignoriert den Fehler, während Sie die Konvertierungsschritte überprüfen, um den Aufruf CopyTo mit einem Aufruf von CopyToAsync zu ersetzen.
Ändern Sie den Namen der Methode, die zu CopyToAsync aufgerufen wird.
Die CopyTo oder CopyToAsync-Methode kopiert Bytes in das Argument, content sinnvollen und gibt keinen 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 Task zurück.Die Aufgabenfunktionen wie "Aufgabe" (void) und ermöglicht die erwartet werden Methode.Wenden Sie Await oder await zum Aufruf von CopyToAsync, wie im folgenden Code veranschaulicht.
Await responseStream.CopyToAsync(content)
await responseStream.CopyToAsync(content);
Die vorherige Anweisung kürzt die folgenden zwei Codezeilen ab.
' 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
// CopyToAsync returns a Task, not a Task<T>. //Task copyTask = responseStream.CopyToAsync(content); // When copyTask is completed, content contains a copy of // responseStream. //await copyTask;
Alles, was in GetURLContents durchgeführt werden, ist, bleibt die Methodensignatur anzupassen.Sie können den Await oder await-Operator nur in Methoden verwenden, die mit dem - Modifizierer Asynchrone (Visual Basic) oder asynchron (C#) gekennzeichnet.Fügen Sie den - Modifizierer hinzu, um die Methode als asynchrone Methode, wie im folgenden Code veranschaulicht zu markieren.
Private Async Function GetURLContents(url As String) As Byte()
private async byte[] GetURLContents(string url)
Der Rückgabetyp einer asynchronen Methode kann Task, Task<TResult> oder void in C# nur sein.In Visual Basic muss die - Methode Function sein, die Task oder Task(Of T) zurückgibt, oder die - Methode muss Sub sein.Normalerweise wird eine Sub-Methode (Visual Basic) oder ein Rückgabetyp void (C#) nur in einem asynchronen Ereignishandler verwendet, in dem Sub oder void erforderlich ist.In anderen Fällen verwenden Sie Task(T), wenn die abgeschlossene Methode eine Return oder Rückgabe-Anweisung, die einen Wert des Typs T zurückgibt, und Sie verwenden Task verfügt, wenn die abgeschlossene Methode keinen sinnvollen Wert zurückgibt.Sie können auch auf den Task Rückgabetyp als Bedeutung Aufgabe "(void) vorstellen."
Weitere Informationen finden Sie unter Asynchrone Rückgabetypen (C# und Visual Basic).
- Methode GetURLContents hat eine return-Anweisung, und die Anweisung gibt ein Bytearray zurück.Daher ist der Rückgabetyp der asynchronen Aufgabe Version (T), der T ein Bytearray ist.Nehmen Sie die folgenden Änderungen in der Methodensignatur vor:
Ändern Sie den Rückgabetyp zu Task(Of Byte()) (Visual Basic) oder zu Task<byte[]> (C#).
Gemäß der Konvention verfügen asynchrone Methoden Namen, die in "asynchronen beenden" umbenennen, sodass Sie die - Methode GetURLContentsAsync.
Im folgenden Code wird diese Änderungen an.
Private Async Function GetURLContentsAsync(url As String) As Task(Of Byte())
private async Task<byte[]> GetURLContentsAsync(string url)
Mit diesen wenigen Änderungen ist die Konvertierung von GetURLContents an einer asynchronen Methode abgeschlossen.
So SumPageSizes zu einer asynchronen Methode konvertieren
Wiederholen Sie die Schritte aus der vorherigen Prozedur für SumPageSizes.Zuerst ändern Sie den Aufruf von GetURLContents zu einem asynchronen Aufruf.
Ändern Sie den Namen der Methode, die von GetURLContents zu GetURLContentsAsync aufgerufen wird, wenn Sie dies nicht bereits getan haben.
Wenden Sie Await oder await Aufgabe, die GetURLContentsAsync zurückgibt, um der Bytearraywert zu erhalten.
Im folgenden Code wird diese Änderungen an.
Dim urlContents As Byte() = Await GetURLContentsAsync(url)
byte[] urlContents = await GetURLContentsAsync(url);
Die vorherige Zuweisung kürzt die folgenden zwei Codezeilen ab.
' 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
// GetURLContentsAsync returns a Task<T>. At completion, the task // produces a byte array. //Task<byte[]> getContentsTask = GetURLContentsAsync(url); //byte[] urlContents = await getContentsTask;
Nehmen Sie die folgenden Änderungen in der Signatur der Methode vor:
Markieren Sie die Methode mit dem Async oder async-Modifizierer.
Fügen Sie "asynchrones" dem Methodennamen hinzu.
Es gibt keine Aufgabenrückgabevariable, T, dieses Mal, da SumPageSizesAsync keinen Wert für T zurückgibt.(Die - Methode hat keine Return oder return-Anweisung.) muss jedoch die - Methode Task zurückgeben, um awaitable zu sein.Daher können Sie eine der folgenden Änderungen:
In Visual Basic ändern Sie den Methodentyp von Sub zu Function.Der Rückgabetyp der Funktion ist Task.
Ändern Sie in C# den Rückgabetyp der Methode von void zu Task.
Im folgenden Code wird diese Änderungen an.
Private Async Function SumPageSizesAsync() As Task
private async Task SumPageSizesAsync()
Die Konvertierung von SumPageSizes zu SumPageSizesAsync ist abgeschlossen.
So startButton_Click zu einer asynchronen Methode konvertieren
Bei ändern Handler, den Namen der aufgerufenen Methode von SumPageSizes zu SumPageSizesAsync, wenn Sie dies nicht bereits getan haben.
Da SumPageSizesAsync eine asynchrone Methode ist, ändern Sie den Code im Ereignishandler, um das Ergebnis zu erwarten.
Der Aufruf SumPageSizesAsync spiegelt den Aufruf CopyToAsync in GetURLContentsAsync.Der Aufruf gibt Task, nicht Task(T).
Wie in vorherigen Prozeduren, können Sie den Aufruf konvertieren, indem Sie eine Anweisung oder zwei - Anweisungen verwenden.Im folgenden Code wird diese Änderungen an.
'' One-step async call. Await SumPageSizesAsync() ' Two-step async call. 'Dim sumTask As Task = SumPageSizesAsync() 'Await sumTask
// One-step async call. await SumPageSizesAsync(); // Two-step async call. //Task sumTask = SumPageSizesAsync(); //await sumTask;
Um den Vorgang versehentlich erneut eingeben zu verhindern, die folgende - Anweisung am Anfang startButton_Click hinzu Start um die Schaltfläche zu deaktivieren.
' Disable the button until the operation is complete. startButton.IsEnabled = False
// 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
// Reenable the button in case you want to run the operation again. startButton.IsEnabled = true;
Weitere Informationen zu Reentranz, finden Sie unter Ablauf des erneuten Eintretens in asynchronen Anwendungen (C# und Visual Basic).
Fügen Sie schließlich den Async oder async-Modifizierer der Deklaration hinzu, damit der Ereignishandler SumPagSizesAsync erwarten kann.
Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
private async void startButton_Click(object sender, RoutedEventArgs e)
In der Regel werden die Namen von Ereignishandlern nicht geändert.Der Rückgabetyp ist auf Task geändert, da Ereignishandler void in C# zurückgeben oder Sub Prozeduren in Visual Basic sein müssen.Daher der Rückgabetyp zu Task.
Die Konvertierung des Projekts von synchronen zur asynchronen Verarbeitung abgeschlossen.
Um die asynchrone Projektmappe testen
Wählen Sie die F5-TASTE, um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start aus.
Geben Sie aus, das der Ausgabe der synchronen Projektmappe sollte werden ähnelt.Beachten Sie jedoch die folgenden Unterschiede.
Alle Ergebnisse nicht treten gleichzeitig auf, nachdem die Verarbeitung abgeschlossen ist.Beispielsweise enthalten beide Programme eine Zeile in startButton_Click, die das Textfeld gelöscht wird.Hiermit ist, das Textfeld zwischen den einzelnen Ausführungen deaktivieren, wenn Sie die Schaltfläche Start für ein zweites Mal auswählen, nachdem ein Resultset aufgetreten ist.In der synchronen Version wird das Textfeld gelöscht, bevor die Anzahl auf den zweiten Mal angezeigt werden, wenn die Downloads abgeschlossen werden und der UI-Thread entscheiden, andere Aufgaben ausführt.Bei der asynchronen Version die Textfeldfreien aufgehoben wird, nachdem Sie die Schaltfläche Start auswählen.
Am wichtigsten ist, wird der UI-Thread nicht während des Downloads blockiert.Sie können das Fenster verschieben oder Größe ändern, während die Webressourcen heruntergeladen, gezählt und angezeigt werden.Wenn eine der Websites langsam oder nicht reagiert ist, können Sie den Vorgang abbrechen, indem Sie die Schaltfläche Schließen auswählen (die x auf den roten Feld in der oberen rechten Ecke).
So GetURLContentsAsync Methode durch eine .NET Framework-Methode ersetzen
. .NET Framework 4.5 bietet viele asynchronen Methoden, die Sie verwenden können.Eine von ihnen, die HttpClient-Methode GetByteArrayAsync(String), führt, ebenso wie Sie für diese exemplarische Vorgehensweise benötigen.Sie können sie anstelle der GetURLContentsAsync-Methode verwenden, die Sie in einer früheren Prozedur erstellt haben.
Der erste Schritt besteht darin, ein HttpClient-Objekt in der - Methode SumPageSizesAsync zu erstellen.Fügen Sie die folgende Deklaration am Anfang der - Methode 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}
// Declare an HttpClient object and increase the buffer size. The // default buffer size is 65,536. HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };
In SumPageSizesAsync, ersetzen Sie den Aufruf der - Methode GetURLContentsAsync mit einem Aufruf der - Methode HttpClient.
Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
byte[] urlContents = await client.GetByteArrayAsync(url);
Entfernen oder kommentieren Sie sie aus GetURLContentsAsync die - Methode, die Sie unter.
Wählen Sie die F5-TASTE, um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start aus.
Das Verhalten dieser Version des Projekts sollte das Verhalten, das die ", Prozedur zu testen asynchroner Projektmappe" jedoch beschreibt, selbst mit weniger Aufwand von Ihnen übereinstimmen.
Beispiel
Der folgende Code enthält das vollständige Beispiel der Konvertierung von einem synchronen zu einer asynchronen Projektmappe, indem er die asynchrone GetURLContentsAsync-Methode, die Sie unter.Beachten Sie, dass es stark der ursprünglichen, synchronen Projektmappe ä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.
' 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/en-us/library/hh290136.aspx",
"https://msdn.microsoft.com/en-us/library/ee256749.aspx",
"https://msdn.microsoft.com/en-us/library/hh290138.aspx",
"https://msdn.microsoft.com/en-us/library/hh290140.aspx",
"https://msdn.microsoft.com/en-us/library/dd470362.aspx",
"https://msdn.microsoft.com/en-us/library/aa578028.aspx",
"https://msdn.microsoft.com/en-us/library/ms404677.aspx",
"https://msdn.microsoft.com/en-us/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 "http://".
Dim displayURL = url.Replace("http://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
// Add the following using directives, and add a reference for System.Net.Http.
using System.Net.Http;
using System.IO;
using System.Net;
namespace AsyncExampleWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void startButton_Click(object sender, RoutedEventArgs e)
{
// Disable the button until the operation is complete.
startButton.IsEnabled = false;
resultsTextBox.Clear();
// One-step async call.
await SumPageSizesAsync();
// Two-step async call.
//Task sumTask = SumPageSizesAsync();
//await sumTask;
resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";
// Reenable the button in case you want to run the operation again.
startButton.IsEnabled = true;
}
private async Task SumPageSizesAsync()
{
// Make a list of web addresses.
List<string> urlList = SetUpURLList();
var total = 0;
foreach (var url in urlList)
{
byte[] urlContents = await GetURLContentsAsync(url);
// The previous line abbreviates the following two assignment statements.
// GetURLContentsAsync returns a Task<T>. At completion, the task
// produces a byte array.
//Task<byte[]> getContentsTask = GetURLContentsAsync(url);
//byte[] urlContents = await getContentsTask;
DisplayResults(url, urlContents);
// Update the total.
total += urlContents.Length;
}
// Display the total count for all of the websites.
resultsTextBox.Text +=
string.Format("\r\n\r\nTotal bytes returned: {0}\r\n", total);
}
private List<string> SetUpURLList()
{
List<string> urls = new List<string>
{
"https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"https://msdn.microsoft.com",
"https://msdn.microsoft.com/en-us/library/hh290136.aspx",
"https://msdn.microsoft.com/en-us/library/ee256749.aspx",
"https://msdn.microsoft.com/en-us/library/hh290138.aspx",
"https://msdn.microsoft.com/en-us/library/hh290140.aspx",
"https://msdn.microsoft.com/en-us/library/dd470362.aspx",
"https://msdn.microsoft.com/en-us/library/aa578028.aspx",
"https://msdn.microsoft.com/en-us/library/ms404677.aspx",
"https://msdn.microsoft.com/en-us/library/ff730837.aspx"
};
return urls;
}
private async Task<byte[]> GetURLContentsAsync(string url)
{
// The downloaded resource ends up in the variable named content.
var content = new MemoryStream();
// Initialize an HttpWebRequest for the current URL.
var webReq = (HttpWebRequest)WebRequest.Create(url);
// Send the request to the Internet resource and wait for
// the response.
using (WebResponse response = await webReq.GetResponseAsync())
// The previous statement abbreviates the following two statements.
//Task<WebResponse> responseTask = webReq.GetResponseAsync();
//using (WebResponse response = await responseTask)
{
// Get the data stream that is associated with the specified url.
using (Stream responseStream = 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>.
//Task copyTask = responseStream.CopyToAsync(content);
// When copyTask is completed, content contains a copy of
// responseStream.
//await copyTask;
}
}
// Return the result as a byte array.
return content.ToArray();
}
private void DisplayResults(string url, byte[] content)
{
// 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.
var bytes = content.Length;
// Strip off the "http://".
var displayURL = url.Replace("http://", "");
resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
}
}
}
Der folgende Code enthält das vollständige Beispiel der Projektmappe, die die HttpClient-Methode verwendet, 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/en-us/library/hh290136.aspx",
"https://msdn.microsoft.com/en-us/library/ee256749.aspx",
"https://msdn.microsoft.com/en-us/library/hh290138.aspx",
"https://msdn.microsoft.com/en-us/library/hh290140.aspx",
"https://msdn.microsoft.com/en-us/library/dd470362.aspx",
"https://msdn.microsoft.com/en-us/library/aa578028.aspx",
"https://msdn.microsoft.com/en-us/library/ms404677.aspx",
"https://msdn.microsoft.com/en-us/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 "http://".
Dim displayURL = url.Replace("http://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
// Add the following using directives, and add a reference for System.Net.Http.
using System.Net.Http;
using System.IO;
using System.Net;
namespace AsyncExampleWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void startButton_Click(object sender, RoutedEventArgs e)
{
resultsTextBox.Clear();
// Disable the button until the operation is complete.
startButton.IsEnabled = false;
// One-step async call.
await SumPageSizesAsync();
//// Two-step async call.
//Task sumTask = SumPageSizesAsync();
//await sumTask;
resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";
// Reenable the button in case you want to run the operation again.
startButton.IsEnabled = true;
}
private async Task SumPageSizesAsync()
{
// Declare an HttpClient object and increase the buffer size. The
// default buffer size is 65,536.
HttpClient client =
new HttpClient() { MaxResponseContentBufferSize = 1000000 };
// Make a list of web addresses.
List<string> urlList = SetUpURLList();
var total = 0;
foreach (var url in urlList)
{
// GetByteArrayAsync returns a task. At completion, the task
// produces a byte array.
byte[] urlContents = await client.GetByteArrayAsync(url);
// The following two lines can replace the previous assignment statement.
//Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
//byte[] urlContents = await getContentsTask;
DisplayResults(url, urlContents);
// Update the total.
total += urlContents.Length;
}
// Display the total count for all of the websites.
resultsTextBox.Text +=
string.Format("\r\n\r\nTotal bytes returned: {0}\r\n", total);
}
private List<string> SetUpURLList()
{
List<string> urls = new List<string>
{
"https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
"https://msdn.microsoft.com",
"https://msdn.microsoft.com/en-us/library/hh290136.aspx",
"https://msdn.microsoft.com/en-us/library/ee256749.aspx",
"https://msdn.microsoft.com/en-us/library/hh290138.aspx",
"https://msdn.microsoft.com/en-us/library/hh290140.aspx",
"https://msdn.microsoft.com/en-us/library/dd470362.aspx",
"https://msdn.microsoft.com/en-us/library/aa578028.aspx",
"https://msdn.microsoft.com/en-us/library/ms404677.aspx",
"https://msdn.microsoft.com/en-us/library/ff730837.aspx"
};
return urls;
}
private void DisplayResults(string url, byte[] content)
{
// 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.
var bytes = content.Length;
// Strip off the "http://".
var displayURL = url.Replace("http://", "");
resultsTextBox.Text += string.Format("\n{0,-58} {1,8}", displayURL, bytes);
}
}
}
Siehe auch
Aufgaben
Gewusst wie: Erweitern der exemplarischen Vorgehensweise mit Task.WhenAll (C# und Visual Basic)
Gewusst wie: Paralleles Erstellen mehrerer Webanforderungen (C# und Visual Basic)
Exemplarische Vorgehensweise: Verwenden des Debuggers mit Async-Methoden
Referenz
Konzepte
Asynchrone Programmierung mit Async und Await (C# und Visual Basic)
Asynchrone Rückgabetypen (C# und Visual Basic)
Verwenden von Async für Dateizugriff (C# und Visual Basic)
Weitere Ressourcen
Asynchrones Beispiel: Auf die Internet-exemplarische Vorgehensweise zugreifen (C# und Visual Basic)
Aufgabenbasierte asynchrone Programmierung (TIPPEN)
Schnellstart: mithilfe des Erwartungsoperators für asynchrone Programmierung