(0) exportieren Drucken
Alle erweitern
Dieser Artikel wurde maschinell übersetzt. Bewegen Sie den Mauszeiger über die Sätze im Artikel, um den Originaltext anzuzeigen. Weitere Informationen
Übersetzung
Original

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

Mit den neuen Funktionen von Visual Studio 2012 können Sie asynchrone Programme einfacher und intuitiver schreiben. Sie können asynchronen Code schreiben, welcher wie synchroner Code aussieht, und dabei den Compiler die schwierigen Rückruffunktionen und die Fortsetzungen (die asynchroner Code normalerweise zur Folge hat) behandeln lassen.

Weitere Informationen über die async-Funktion, finden Sie unter Asynchrone Programmierung mit Async und Await (C# und Visual Basic).

Dieser Schnelleinstiegsartikel startet einer synchronen WPF-Anwendung (Windows Presentation Foundation), welche die Anzahl der Bytes in einer Liste von Websites summiert. Anschließend wird die Implementierung der Anwendung asynchron gemacht, indem die neuen Funktionen verwendet werden.

Wenn Sie die Anwendungen nicht selbst erstellen möchten, können Sie "Async Beispiel: Zugriff auf das Web Schnelleinstieg (C# und Visual Basic)" aus den Entwickler-Codebeispielen herunterladen.

In diesem Schnelleinstiegsartikel führen Sie folgende Aufgaben aus:

Visual Studio 2012 muss auf dem Computer installiert werden. Weitere Informationen finden Sie auf der Microsoft-Website.

So erstellen Sie eine WPF-Anwendung

  1. Starten Sie Visual Studio.

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

    Das Dialogfeld Neues Projekt wird angezeigt.

  3. Im Bereich Installierte Vorlagen wählen Sie Visual Basic oder Visual C# aus. Anschließend wählen Sie WPF-Anwendung aus der Liste der Projekttypen.

  4. Im Textfeld Name geben Sie "AsyncExampleWPF" ein und klicken dann auf die Schaltfläche OK.

    Das neue Projekt wird im Projektmappen-Explorer angezeigt.

So fügen Sie ein einfaches WPF MainWindow entwerfen

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

  2. Wenn das Werkzeugkasten-Fenster nicht sichtbar ist, öffnen Sie im Hauptmenü Ansicht und wählen Sie dann den Werkzeugkasten aus.

  3. Fügen Sie ein Button-Steuerelement und ein TextBox-Steuerelement dem Hauptfenster (MainWindow) hinzu.

  4. Markieren Sie das TextBox-Steuerelement und setzen Sie die folgenden Eingenschaften im Eigenschaften-Fenster:

    • Setzen Sie die Name-Eigenschaft auf resultsTextBox.

    • Setzen Sie die Height-Eigenschaft auf 250.

    • Setzen Sie die Width-Eigenschaft auf 500.

    • Wählen Sie eine monospaced-Schriftart (z.B. Lucida Console oder Global Monospace) auf der Text-Registerkarte aus.

  5. Markieren Sie das Button-Steuerelement und setzen Sie folgende Eigenschaften im Eigenschaften-Fenster:

    • Setzen Sie die Name-Eigenschaft auf startButton.

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

  6. Positionieren Sie das Textfeld und die Schaltfläche, damit beide im Hauptfenster angezeigt werden.

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

So fügen Sie einen Verweis hinzu

  1. Markieren Sie im Projektmappenexplorer Ihr Projekt.

  2. Wählen Sie im Hauptmenü Projekt => Verweis hinzufügen aus.

    Der Verweismanager wird angezeigt.

  3. Überprüfen Sie am oberen Rand des Dialogfelds, dass Ihr Projekt auf das .NET Framework 4.5 abzielt.

  4. Im Bereich Assemblies wählen Sie Framework aus, wenn dies nicht bereits ausgewählt ist.

  5. Aktivieren Sie in der Namensliste das Kontrollkästchen für System.Net.Http.

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

So fügen Sie erforderliche Imports-Anweisungen oder using-Direktiven hinzu

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

  2. Fügen Sie die folgenden Imports-Anweisungen (Visual Basic) oder using-Direktiven (C#) am Anfang der Codedatei hinzu, wenn sie noch nicht vorhanden sind.

    
    using System.Net.Http;
    using System.Net;
    using System.IO;
    
    
    

Um eine synchrone Anwendung erstellen

  1. In der Entwurfsansicht von MainWindow.xaml, Klicken Sie die Start-Schaltfläche doppelt an, um den startButton_Click-Ereignishandler in MainWindow.xaml.vb oder MainWindow.xaml.cs zu erstellen. Als Alternative selektieren Sie die Start-Schaltfläche, aktivieren das Ereignishandler für die ausgewählten Elemente-Symbol im Eigenschaften-Fenster, und geben Sie dann startButton_Click im Textfeld ein. Sie können ebenfalls das Textfeld doppelt klicken. Dann wird der Ereignishandler automatisch erzeugt.

  2. Kopieren Sie den folgenden Code in den Methodenrumpf des Ereignishandlers startButton_Click in der Datei MainWindow.xaml.vb oder MainWindow.xaml.cs.

    
    resultsTextBox.Clear();
    SumPageSizes();
    resultsTextBox.Text += "\r\nControl returned to startButton_Click.";
    
    
    

    Der Code ruft die SumPageSizes-Methode auf, die die Anwendung steuert, und zeigt eine Meldung an, wenn die Steuerung an startButton_Click zurückgeht.

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

    • SumPageSizes, ruft eine Liste der Webseiten-URLs von SetUpURLList ab, und verarbeitet dann mit GetURLContents und DisplayResults jede dieser URLs.

    • SetUpURLList erstellt eine Liste von Webadressen und gibt diese zurück.

    • GetURLContents lädt den Inhalt jeder Website herunter und gibt den Inhalt als Bytearray zurück.

    • DisplayResults zeigt die Anzahl von Bytes im Bytearray für jede URL an.

    Kopieren Sie die folgenden vier Methoden und fügen Sie diese unter dem startButton_Click-Ereignishandler in MainWindow.xaml.vb oder MainWindow.xaml.cs ein.

    
    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> 
        { 
            "http://msdn.microsoft.com/library/windows/apps/br211380.aspx",
            "http://msdn.microsoft.com",
            "http://msdn.microsoft.com/en-us/library/hh290136.aspx",
            "http://msdn.microsoft.com/en-us/library/ee256749.aspx",
            "http://msdn.microsoft.com/en-us/library/hh290138.aspx",
            "http://msdn.microsoft.com/en-us/library/hh290140.aspx",
            "http://msdn.microsoft.com/en-us/library/dd470362.aspx",
            "http://msdn.microsoft.com/en-us/library/aa578028.aspx",
            "http://msdn.microsoft.com/en-us/library/ms404677.aspx",
            "http://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.
        // Note: you can't use HttpWebRequest.GetResponse in a Windows Store app.
        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.

    Sie sollten eine ähnliche Ausgabe wie die folgende erhalten.

    
    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 es einige Sekunden benötigt, um die Anzahl anzuzeigen. Während dieser Zeit wird der UI-Thread blockiert, da er auf das Herunterladen der angeforderten Ressourcen wartet. Daher können Sie das Fenster nicht verschieben, maximieren, minimieren oder sogar schließen, nachdem Sie die Start-Schaltfläche ausgewählt haben. Diese Bemühungen schlagen fehl, bis die Anzahl der Bytes in der Ausgabe erscheint. Wenn eine Website nicht reagiert, haben Sie keinen Hinweis darauf, welche von den Seiten nicht heruntergeladen werden konnte. Es ist sogar genauso schwierig das Warten zu beenden und das Programm zu schließen.

    Vergleichen Sie dieses Verhalten mit dem Verhalten der Anwendung, nachdem Sie diese in eine asynchronen Lösung geändert haben.

So GetURLContents zu einer asynchronen Methode konvertieren

  1. Um die synchrone Lösung zu einer asynchronen Lösung zu konvertieren, ist der beste Ort zumBeginnen die Methode GetURLContents, da die Aufrufe derMethoden HttpWebRequestGetResponse und Stream.CopyTo diejenigen sind, die auf das Internet zugreifen. Das .NET Framework macht die Konvertierung einfach, indem asynchrone Versionen beider Methoden existieren.

    Weitere Informationen über die Methoden, die in GetURLContents verwendet werden, finden Sie unter WebRequest.

    Hinweis Hinweis

    Wenn Sie die Schritte in diesem Schnelleinstieg folgen, werden einige Compilerfehler auftreten. Sie können diese Fehler ignorieren und mit dem Schnelleinstieg fortfahren.

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

    using (WebResponse response = webReq.GetResponseAsync())
    
  2. GetResponseAsync gibt ein Objekt des Typs Task<TResult> zurück. In diesem Fall ist der Typ der Task-Rückgabevariable, TResult, vom Typ WebResponse. Die Task ist eine Zusicherung, dass am Ende ein WebResponse-Objekt erzeugt wird, nachdem die angeforderten Daten heruntergeladen und die Aufgabe abgeschlossen wurde.

    Um den Um den WebResponse-Wert von der Task abzurufen, wenden Sie den Operator Await (Visual Basic) oder await (C#) zum Aufruf von GetResponseAsync an, wie im folgenden Code veranschaulicht.

    Rechnen Sie (Visual Basic) Sie erwarten (C#)

    
    using (WebResponse response = await webReq.GetResponseAsync())
    
    
    

    Der await-Operator hält die Ausführung der aktuellen Methode GetURLContents an, bis die erwartete Aufgabe abgeschlossen ist. Inzwischen kehrt die Steuerung an den Aufrufer der aktuellen Methode zurück. In diesem Beispiel ist die aktuelle Methode GetURLContents und die aufrufende Methode ist SumPageSizes. Wenn die Aufgabe beendet ist, wird das zugesicherte WebResponse-Objekt als Wert der erwarteten Aufgabe erzeugt und der Variablen response zugewiesen.

    Die vorherige Anweisung kann in die folgenden beiden Anweisungen getrennt werden, um zu erläutern was genau geschieht.

    
    //Task<WebResponse> responseTask = webReq.GetResponseAsync();
    //using (WebResponse response = await responseTask)
    
    
    

    Der Aufruf webReq.GetResponseAsync gibt in VB.NET ein Objekt des Typs Task(Of WebResponse) und in C# ein Objekt des Typs Task<WebResponse> zurück. Anschließend wird der await-Operator auf der zurückgegebenen Task angewendet, um den Wert des Typs WebResponse abzurufen.

    Wenn die asynchrone Methode Arbeit auszuführen hat, die nicht vom Abschluss der Task abhängig ist, dann kann diese Arbeit zwischen den beiden Anweisungen, nach dem Aufruf der asynchronen Methode und vor dem await-Operator, durchgeführt werden. Beispiele zu diesem Thema finden Sie unter Gewusst wie: Paralleles Erstellen mehrerer Webanforderungen mit Async and Await (C# und Visual Basic) und Gewusst wie: Erweitern der asynchronen exemplarischen Vorgehensweise mit Task.WhenAll (C# und Visual Basic).

  3. 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 Async- (Visual Basic) oder dem async-Modifizierer (C#) gekennzeichnet sind.

    Asynchrone (Visual Basic)

    asynchron (C#) gekennzeichnet.

    Ignorieren Sie den Fehler während Sie die Aufrufe von CopyTo mit Aufrufen von CopyToAsync ersetzen.

    • Ändern Sie den Namen der aufgerufenen Methode zu CopyToAsync.

    • Die CopyTo- oder CopyToAsync-Methoden kopieren Bytes in das Argument content und geben keinen bedeutsamen 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 Objekt vom Typ Task zurück. Die Task funktioniert wie Task(void) und ermöglicht es, dass die Methode "erwartet" bzw. abgewartet werden kann. Wenden Sie Await (Visual Basic) oder await (C#) beim Aufruf von CopyToAsync an, wie im folgenden Code veranschaulicht.

      
      await responseStream.CopyToAsync(content);
      
      
      

      Die vorherige Anweisung ist eine Verkürzung der folgenden zwei Codezeilen.

      
      // 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;
      
      
      
  4. Alles was in GetURLContents gemacht werden muss, ist die Methodensignatur anzupassen.

    Sie können den Await oder await-Operator nur in Methoden verwenden, die mit dem Async- Modifizierer (Visual Basic) oder dem async-Modifizierer (C#) gekennzeichnet sind.

    Asynchrone (Visual Basic) oder asynchron (C#)

    Fügen Sie den Modifizierer hinzu, um die Methode als asynchrone Methode zu markieren. Der folgende Code veranschaulicht dies.

    private async byte[] GetURLContents(string url)
    
    
  5. Der Rückgabetyp einer async-Methode kann in C# nur Task, Task<TResult> oder void sein. In Visual Basic muss die Methode eine Function sein, die Task oder Task(Of T) zurückgibt. Ansonsten muss die Methode eine 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 Methode eine Return oder return-Anweisung hat, die einen Wert des Typs T zurückgibt. Verwenden Sie Task, wenn die Methode keinen sinnvollen Wert zurückgibt.

    Rückgabe

    Sie können Sich den Task-Rückgabetyp als "Task(void)" vorstellen.

    Weitere Informationen finden Sie unter Asynchrone Rückgabetypen (C# und Visual Basic).

    Die Methode GetURLContents hat eine return-Anweisung, die ein Bytearray zurückgibt. Daher ist der Rückgabetyp der asynchronen Methode vom Typ Task(T), wobei 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 über Namen, die mit "Async" enden. Benennen Sie daher die Methode in GetURLContentsAsync um.

    Der folgende Code zeigt die Änderungen.

    
    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

  1. Wiederholen Sie die Schritte aus der vorherigen Prozedur für die Methode SumPageSizes. Zuerst ändern Sie den Aufruf von GetURLContents zu einem asynchronen Aufruf.

    • Ändern Sie den Namen der Methode von GetURLContents zu GetURLContentsAsync, wenn Sie dies nicht bereits getan haben.

    • Wenden Sie Await oder await auf die Task an, die GetURLContentsAsync zurückgibt, um den Bytearraywert zu erhalten.

    Der folgende Code zeigt die Änderungen.

    
    byte[] urlContents = await GetURLContentsAsync(url);
    
    
    

    Die vorherige Zuweisung kürzt die folgenden zwei Codezeilen ab.

    
    // GetURLContentsAsync returns a Task<T>. At completion, the task
    // produces a byte array.
    //Task<byte[]> getContentsTask = GetURLContentsAsync(url);
    //byte[] urlContents = await getContentsTask;
    
    
    
  2. Nehmen Sie die folgenden Änderungen in der Signatur der Methode vor:

    • Markieren Sie die Methode mit dem Async- oder async-Modifizierer.

    • Fügen Sie "Async" dem Methodennamen hinzu.

    • Es gibt keine Task-Rückgabevariable T dieses Mal, da SumPageSizesAsync keinen Wert für T zurückgibt. Die Methode hat keine Return oder return-Anweisung, muss jedoch eine Task zurückgeben, um awaitable zu sein. Führen Sie daher eine der folgenden Änderungen durch:

      • 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.

    Der folgende Code zeigt die Änderungen.

    
    private async Task SumPageSizesAsync()
    
    
    

    Die Konvertierung von SumPageSizes zu SumPageSizesAsync ist abgeschlossen.

So startButton_Click zu einer asynchronen Methode konvertieren

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

  2. 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 ein Objekt vom Typ Task, nicht vom Typ Task(T) zurück.

    Wie in vorherigen Prozeduren, können Sie den Aufruf konvertieren, indem Sie eine oder zwei Anweisungen verwenden. Der folgende Code zeigt die Änderungen.

    
    // One-step async call.
    await SumPageSizesAsync();
    
    // Two-step async call.
    //Task sumTask = SumPageSizesAsync();
    //await sumTask;
    
    
    
  3. Um ein versehentliches erneutes Ausführen der Operation zu verhindern, fügen Sie die folgende Anweisung am Anfang des Ereignishandlers startButton_Click hinzu, um die Schaltfläche 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 Wiedereintritt finden Sie unter Ablauf des erneuten Eintretens in asynchronen Anwendungen (C# und Visual Basic).

  4. Fügen Sie schließlich den Async oder async-Modifizierer der Deklaration hinzu, damit der Ereignishandler SumPagSizesAsync erwarten kann.

    
    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. Ändern Sie daher den Rückgabetyp zu Task.

    Die Konvertierung des Projektes von einer synchronen zur einer asynchronen Verarbeitung ist nun abgeschlossen.

Um die asynchrone Projektmappe testen

  1. Drücken Sie die F5-TASTE um das Programm auszuführen, und wählen Sie dann die Schaltfläche Start aus.

  2. Es sollte eine Ausgabe erscheinen, die der Ausgabe der synchronen Lösuing ähnelt. Beachten Sie jedoch die folgenden Unterschiede.

    • Alle Ergebnisse treten nicht gleichzeitig auf, nachdem die Verarbeitung abgeschlossen ist. Beispielsweise enthalten beide Programme eine Zeile in startButton_Click, die das Textfeld löschen. Das Ziel ist es, das Textfeld zwischen den einzelnen Ausführungen zu leeren, wenn Sie die Schaltfläche Start für ein zweites Mal auswählen. In der synchronen Version wird das Textfeld gelöscht, bevor die Anzahl der Bytes der zweiten Durchführung angezeigt werden, nachdem die Downloads abgeschlossen wurden und der UI-Thread frei ist um andere Aufgaben auszuführen. Bei der asynchronen Version wird das Textfeld geleert, nachdem Sie die Schaltfläche Start auswählen.

    • Am wichtigsten ist, dass der UI-Thread nicht während des Downloads blockiert wird. Sie können das Fenster verschieben oder die 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 (das X im roten Feld in der oberen rechten Ecke des Fesnters).

So GetURLContentsAsync Methode durch eine .NET Framework-Methode ersetzen

  1. Das .NET Framework 4.5 bietet viele asynchrone Methoden die Sie verwenden können. Eine von ihnen, die HttpClient-Methode GetByteArrayAsync(String), ist die Methode, die Sie für diesen Schnelleinstieg 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.
    HttpClient client =
        new HttpClient() { MaxResponseContentBufferSize = 1000000 };
    
    
    
  2. In SumPageSizesAsync, ersetzen Sie den Aufruf der Methode GetURLContentsAsync mit einem Aufruf der HttpClient-Methode.

    
    byte[] urlContents = await client.GetByteArrayAsync(url);               
    
    
    
  3. Entfernen oder kommentieren Sie die GetURLContentsAsync aus, die Sie vorher erstellt haben.

  4. 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 Projektes, sollte das Verhalten der Prozedur, die unter "Prozedur zum testen der asynchroner Projektmappe" beschrieben ist, übereinstimmen. Nur mit weniger Aufwand von Ihrer Seite.

Der folgende Code enthält das vollständige Beispiel der Konvertierung von einem synchronen zu einer asynchronen Lösung, indem die asynchrone GetURLContentsAsync-Methode verwendet wird, die Sie implementiert haben. Beachten Sie, dass sie stark der ursprünglichen, synchronen Lösung ähnelt.


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> 
            { 
                "http://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "http://msdn.microsoft.com",
                "http://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "http://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "http://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "http://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "http://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "http://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "http://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "http://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 Lösung, welche die HttpClient-Methode GetByteArrayAsync verwendet.


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> 
            { 
                "http://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "http://msdn.microsoft.com",
                "http://msdn.microsoft.com/en-us/library/hh290136.aspx",
                "http://msdn.microsoft.com/en-us/library/ee256749.aspx",
                "http://msdn.microsoft.com/en-us/library/hh290138.aspx",
                "http://msdn.microsoft.com/en-us/library/hh290140.aspx",
                "http://msdn.microsoft.com/en-us/library/dd470362.aspx",
                "http://msdn.microsoft.com/en-us/library/aa578028.aspx",
                "http://msdn.microsoft.com/en-us/library/ms404677.aspx",
                "http://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);
        }
    }
}


Community-Beiträge

HINZUFÜGEN
Anzeigen:
© 2014 Microsoft