Exemplarische Vorgehensweise: Zugreifen auf das Web mit async und await (C#)Walkthrough: Accessing the Web by Using async and await (C#)

Sie können asynchrone Programme mit den Funktionen „Async/Await“ einfacher und intuitiver schreiben.You can write asynchronous programs more easily and intuitively by using async/await features. 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.You can write asynchronous code that looks like synchronous code and let the compiler handle the difficult callback functions and continuations that asynchronous code usually entails.

Weitere Informationen über die Funktion „Async“ finden Sie unter Asynchronous Programming with async and await (C#) (Asynchrone Programmierung mit Async und Await (C#)).For more information about the Async feature, see Asynchronous Programming with async and await (C#).

Diese exemplarische Vorgehensweise beginnt mit einer synchronen WPF-Anwendung (Windows Presentation Foundation), die die Anzahl der Bytes in einer Liste von Websites summiert.This walkthrough starts with a synchronous Windows Presentation Foundation (WPF) application that sums the number of bytes in a list of websites. In der exemplarischen Vorgehensweise wird die Anwendung dann mithilfe der neuen Funktionen in eine asynchrone Lösung umgewandelt.The walkthrough then converts the application to an asynchronous solution by using the new features.

Wenn Sie die Anwendungen nicht selbst erstellen möchten, können Sie Async Sample: Accessing the Web Walkthrough (C# and Visual Basic) (Asynchrones Beispiel: Webzugriff – Exemplarische Vorgehensweise (C# und Visual Basic)) herunterladen.If you don't want to build the applications yourself, you can download Async Sample: Accessing the Web Walkthrough (C# and Visual Basic).

Im Verlauf dieser exemplarischen Vorgehensweise führen Sie folgende Aufgaben aus:In this walkthrough, you complete the following tasks:

Hinweis

Zum Ausführen der Beispiele müssen Visual Studio 2012 oder höher sowie .NET Framework 4.5 oder höher auf dem Computer installiert sein.To run the examples, you must have Visual Studio 2012 or newer and the .NET Framework 4.5 or newer installed on your computer.

So erstellen Sie eine WPF-AnwendungTo create a WPF application

  1. Starten Sie Visual Studio.Start Visual Studio.

  2. Wählen Sie in der Menüleiste Datei, Neu, Projektaus.On the menu bar, choose File, New, Project.

    Das Dialogfeld Neues Projekt wird angezeigt.The New Project dialog box opens.

  3. Wählen Sie im Bereich Installierte Vorlagen den Eintrag Visual C# aus, und wählen Sie dann in der Liste der Projekttypen WPF-Anwendung aus.In the Installed Templates pane, choose Visual C#, and then choose WPF Application from the list of project types.

  4. Geben Sie im Textfeld Name AsyncExampleWPF ein, und wählen Sie dann die Schaltfläche OK aus.In the Name text box, enter AsyncExampleWPF, and then choose the OK button.

    Das neue Projekt wird im Projektmappen-Explorer angezeigt.The new project appears in Solution Explorer.

So entwerfen Sie ein einfaches WPF-MainWindowTo design a simple WPF MainWindow

  1. Wählen Sie im Visual Studio Code Editor die Registerkarte MainWindow.xaml aus.In the Visual Studio Code Editor, choose the MainWindow.xaml tab.

  2. Wenn das Fenster Toolbox nicht sichtbar ist, öffnen Sie das Menü Ansicht, und wählen Sie dann Toolbox aus.If the Toolbox window isn’t visible, open the View menu, and then choose Toolbox.

  3. Fügen Sie dem Fenster MainWindow ein Button-Steuerelement und ein TextBox-Steuerelement hinzu.Add a Button control and a TextBox control to the MainWindow window.

  4. Markieren Sie das TextBox-Steuerelement, und legen Sie im Fenster Eigenschaften die folgenden Werte fest:Highlight the TextBox control and, in the Properties window, set the following values:

    • Legen Sie die Eigenschaft Name auf resultsTextBox fest.Set the Name property to resultsTextBox.

    • Legen Sie die Eigenschaft Height auf „250“ fest.Set the Height property to 250.

    • Legen Sie die Eigenschaft Width auf „500“ fest.Set the Width property to 500.

    • Geben Sie auf der Registerkarte Text eine Festbreitenschriftart wie Lucida Console oder Global Monospace an.On the Text tab, specify a monospaced font, such as Lucida Console or Global Monospace.

  5. Markieren Sie das Button-Steuerelement, und legen Sie im Fenster Eigenschaften die folgenden Werte fest:Highlight the Button control and, in the Properties window, set the following values:

    • Legen Sie die Eigenschaft Name auf startButton fest.Set the Name property to startButton.

    • Ändern Sie den Wert der Eigenschaft Content von Button zu Start.Change the value of the Content property from Button to Start.

  6. Positionieren Sie das Textfeld und die Schaltfläche so, dass beide im Fenster MainWindow angezeigt werden.Position the text box and the button so that both appear in the MainWindow window.

    Weitere Informationen über den WPF-XAML-Designer finden Sie unter Erstellen einer Benutzeroberfläche mit dem XAML-Designer.For more information about the WPF XAML Designer, see Creating a UI by using XAML Designer.

So fügen Sie einen Verweis hinzuTo add a reference

  1. Markieren Sie im Projektmappen-Explorer den Namen des Projekts.In Solution Explorer, highlight your project's name.

  2. Wählen Sie in der Menüleiste die Optionen Projekt und Verweis hinzufügen aus.On the menu bar, choose Project, Add Reference.

    Das Dialogfeld Verweis-Manager wird angezeigt.The Reference Manager dialog box appears.

  3. Stellen Sie oben im Dialogfeld sicher, dass Ihr Projekt auf .NET Framework 4.5 oder höher abzielt.At the top of the dialog box, verify that your project is targeting the .NET Framework 4.5 or higher.

  4. Wählen Sie im Bereich Assemblys die Option Framework aus, wenn sie nicht bereits ausgewählt ist.In the Assemblies area, choose Framework if it isn’t already chosen.

  5. Aktivieren Sie in der Liste der Namen das Kontrollkästchen System.Net.Http.In the list of names, select the System.Net.Http check box.

  6. Wählen Sie die Schaltfläche OK aus, um das Dialogfeld zu schließen.Choose the OK button to close the dialog box.

So fügen Sie erforderliche using-Anweisungen hinzuTo add necessary using directives

  1. Öffnen Sie im Projektmappen-Explorer das Kontextmenü für „MainWindow.xaml.cs“, und wählen Sie dann Code anzeigen aus.In Solution Explorer, open the shortcut menu for MainWindow.xaml.cs, and then choose View Code.

  2. Fügen Sie die folgenden using-Anweisungen am Anfang der Codedatei ein, wenn sie noch nicht vorhanden sind.Add the following using directives at the top of the code file if they’re not already present.

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

So erstellen Sie eine synchrone AnwendungTo create a synchronous application

  1. Doppelklicken Sie im Entwurfsfenster „MainWindow.xaml“ auf die Schaltfläche Start, um den startButton_Click-Ereignishandler in „MainWindow.xaml.cs“ zu erstellen.In the design window, MainWindow.xaml, double-click the Start button to create the startButton_Click event handler in MainWindow.xaml.cs.

  2. Kopieren Sie in „MainWindow.xaml.cs“ den folgenden Code in den Textteil von startButton_Click:In MainWindow.xaml.cs, copy the following code into the body of startButton_Click:

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

    Der Code ruft die Methode SumPageSizes auf, die die Anwendung steuert und zeigt eine Meldung an, wenn das Steuerelement zu startButton_Click zurückgegeben wird.The code calls the method that drives the application, SumPageSizes, and displays a message when control returns to startButton_Click.

  3. Der Code für die synchrone Lösung enthält die folgenden vier Methoden:The code for the synchronous solution contains the following four methods:

    • SumPageSizes. Enthält eine Liste von Webseiten-URLs aus SetUpURLList und ruft dann GetURLContents und DisplayResults auf, um jede URL zu verarbeiten.SumPageSizes, which gets a list of webpage URLs from SetUpURLList and then calls GetURLContents and DisplayResults to process each URL.

    • SetUpURLList. Erstellt und gibt eine Liste der Webadressen zurück.SetUpURLList, which makes and returns a list of web addresses.

    • GetURLContents. Lädt Inhalte jeder Website herunter und gibt die Inhalte als ein Bytearray zurück.GetURLContents, which downloads the contents of each website and returns the contents as a byte array.

    • DisplayResults. Zeigt die Anzahl der Bytes im Bytearray für jede URL an.DisplayResults, which displays the number of bytes in the byte array for each URL.

    Kopieren Sie die folgenden vier Methoden, und fügen Sie sie dann unter dem startButton_Click-Ereignishandler in „MainWindow.xaml.cs“ ein:Copy the following four methods, and then paste them under the startButton_Click event handler in MainWindow.xaml.cs:

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

So testen Sie die synchrone LösungTo test the synchronous solution

  1. Drücken Sie die Taste F5, um das Programm auszuführen, und klicken Sie dann auf die Schaltfläche Starten .Choose the F5 key to run the program, and then choose the Start button.

    Die Ausgabe sollte der folgenden Liste gleichen.Output that resembles the following list should appear.

    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.Notice that it takes a few seconds to display the counts. Während dieser Zeit ist der Benutzeroberflächenthread blockiert, während auf das Herunterladen von angeforderten Ressourcen gewartet wird.During that time, the UI thread is blocked while it waits for requested resources to download. Daher können Sie das Anzeigefenster weder verschieben, maximieren, minimieren noch schließen, nachdem Sie die Schaltfläche Start ausgewählt haben.As a result, you can't move, maximize, minimize, or even close the display window after you choose the Start button. Diese Bemühungen sind nicht erfolgreich, bis der Bytezähler angezeigt wird.These efforts fail until the byte counts start to appear. Wenn eine Website nicht antwortet, erhalten Sie keinen Hinweis darüber, welche Site fehlerhaft ist.If a website isn’t responding, you have no indication of which site failed. Es ist sogar schwierig, mit dem Warten aufzuhören und das Programm zu schließen.It is difficult even to stop waiting and close the program.

So konvertieren Sie „GetURLContents“ in eine asynchrone MethodeTo convert GetURLContents to an asynchronous method

  1. Für das Konvertieren der synchronen Projektmappe in eine asynchrone Projektmappe empfiehlt es sich, in GetURLContents zu beginnen, da die Aufrufe der HttpWebRequest-Methode GetResponse und der Stream-Methode CopyTo dort erfolgen, wo die Anwendung auf das Web zugreift.To convert the synchronous solution to an asynchronous solution, the best place to start is in GetURLContents because the calls to the HttpWebRequest method GetResponse and to the Stream method CopyTo are where the application accesses the web. .NET Framework erleichtert die Konvertierung, indem asynchrone Versionen beider Methoden bereitgestellt werden.The .NET Framework makes the conversion easy by supplying asynchronous versions of both methods.

    Weitere Informationen über die in GetURLContents verwendeten Methoden finden Sie unter WebRequest.For more information about the methods that are used in GetURLContents, see WebRequest.

    Hinweis

    Beim Befolgen der Schritte in dieser exemplarischen Vorgehensweise treten verschiedene Compilerfehler auf.As you follow the steps in this walkthrough, several compiler errors appear. Sie können diese ignorieren und mit der exemplarischen Vorgehensweise fortfahren.You can ignore them and continue with the walkthrough.

    Ändern Sie die Methode, die aufgerufen wird, in der dritten Zeile von GetURLContents von GetResponse zur asynchronen, aufgabenbasierten GetResponseAsync-Methode.Change the method that's called in the third line of GetURLContents from GetResponse to the asynchronous, task-based GetResponseAsync method.

    using (WebResponse response = webReq.GetResponseAsync())  
    
  2. GetResponseAsync gibt einen Wert vom Typ Task<TResult> zurück.GetResponseAsync returns a Task<TResult>. In diesem Fall weist die Aufgabenrückgabevariable, TResult, den Typ WebResponse auf.In this case, the task return variable, TResult, has type WebResponse. Mit dieser Aufgabe soll ein tatsächliches WebResponse-Objekt erstellt werden, nachdem die angeforderten Daten heruntergeladen und das Ausführen der Aufgabe abgeschlossen wurde.The task is a promise to produce an actual WebResponse object after the requested data has been downloaded and the task has run to completion.

    Wenden Sie analog zur Darstellung im folgenden Code zum Abrufen des WebResponse-Werts aus der Aufgabe einen await-Operator für den Aufruf von GetResponseAsync an.To retrieve the WebResponse value from the task, apply an await operator to the call to GetResponseAsync, as the following code shows.

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

    Der await-Operator hält die Ausführung der aktuellen Methode GetURLContents an, bis die Aufgabe abgeschlossen ist.The await operator suspends the execution of the current method, GetURLContents, until the awaited task is complete. In der Zwischenzeit kehrt die Steuerung zum Aufrufer der aktuellen Methode zurück.In the meantime, control returns to the caller of the current method. In diesem Beispiel lautet die aktuelle Methode GetURLContents, und der Aufrufer ist SumPageSizes.In this example, the current method is GetURLContents, and the caller is SumPageSizes. Wenn die Aufgabe abgeschlossen ist, wird das zugesicherte WebResponse-Objekt als Wert der erwarteten Aufgabe erstellt und zur Variable response zugewiesen.When the task is finished, the promised WebResponse object is produced as the value of the awaited task and assigned to the variable response.

    Die vorherige Anweisung kann in die folgenden zwei Anweisungen getrennt werden, um zu verdeutlichen, was geschieht.The previous statement can be separated into the following two statements to clarify what happens.

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

    Durch den Aufruf von webReq.GetResponseAsync wird Task(Of WebResponse) oder Task<WebResponse> zurückgegeben.The call to webReq.GetResponseAsync returns a Task(Of WebResponse) or Task<WebResponse>. Anschließend wird ein await-Operator auf die Aufgabe angewendet, um den WebResponse-Wert abzurufen.Then an await operator is applied to the task to retrieve the WebResponse value.

    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.If your async method has work to do that doesn’t depend on the completion of the task, the method can continue with that work between these two statements, after the call to the async method and before the await operator is applied. Beispiele finden Sie unter How to: Make Multiple Web Requests in Parallel by Using async and await (C#) (Vorgehensweise: Gleichzeitiges Erstellen von mehreren Webanforderungen mit „Async“ und „Await“ (C#)) und Vorgehensweise: Erweitern der asynchronen exemplarischen Vorgehensweise mit Task.WhenAll (C#).For examples, see How to: Make Multiple Web Requests in Parallel by Using async and await (C#) and How to: Extend the async Walkthrough by Using Task.WhenAll (C#).

  3. Da Sie den Operator await im vorherigen Schritt hinzugefügt haben, tritt ein Compilerfehler auf.Because you added the await operator in the previous step, a compiler error occurs. Der Operator kann nur in Methoden verwendet werden, die mit dem Modifizierer async markiert sind.The operator can be used only in methods that are marked with the async modifier. Ignorieren Sie den Fehler, während Sie die Konvertierungsschritte zum Ersetzen des Aufrufs von CopyTo mit einem Aufruf von CopyToAsync wiederholen.Ignore the error while you repeat the conversion steps to replace the call to CopyTo with a call to CopyToAsync.

    • Ändern Sie den Namen der Methode, die für CopyToAsync aufgerufen wird.Change the name of the method that’s called to CopyToAsync.

    • Die Methode CopyTo oder CopyToAsync kopiert Bytes zu ihrem Argument content und gibt keinen sinnvollen Wert zurück.The CopyTo or CopyToAsync method copies bytes to its argument, content, and doesn’t return a meaningful value. In der synchronen Version ist der Aufruf von CopyTo eine einfache Anweisung, die keinen Wert zurückgibt.In the synchronous version, the call to CopyTo is a simple statement that doesn't return a value. Die asynchrone Version CopyToAsync gibt ein Task zurück.The asynchronous version, CopyToAsync, returns a Task. Die Aufgabe funktioniert wie „Task(void)“ und ermöglicht, dass auf die Methode gewartet wird.The task functions like "Task(void)" and enables the method to be awaited. Wenden Sie Await oder await auf den Aufruf von CopyToAsync an, wie dies im folgenden Code gezeigt wird.Apply Await or await to the call to CopyToAsync, as the following code shows.

      await responseStream.CopyToAsync(content);  
      

      Die vorherige Anweisung kürzt die folgenden zwei Codezeilen.The previous statement abbreviates the following two lines of code.

      // 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. Somit muss nur noch die Methodensignatur in GetURLContents angepasst werden.All that remains to be done in GetURLContents is to adjust the method signature. Der await-Operator kann nur in Methoden verwendet werden, die mit dem Modifizierer async markiert sind.You can use the await operator only in methods that are marked with the async modifier. Fügen Sie den Modifizierer hinzu, um die Methode als eine async-Methode zu markieren, wie im folgenden Code gezeigt wird.Add the modifier to mark the method as an async method, as the following code shows.

    private async byte[] GetURLContents(string url)  
    
  5. Der Rückgabetype einer async-Methode kann nur Task, Task<TResult> oder void in C# sein.The return type of an async method can only be Task, Task<TResult>, or void in C#. Für gewöhnlich wird ein Rückgabetyp void nur in einem asynchronen Ereignishandler verwendet, bei dem void erforderlich ist.Typically, a return type of void is used only in an async event handler, where void is required. In anderen Fällen verwenden Sie Task(T), wenn die abgeschlossene Methode eine return-Anweisung aufweist, die einen Wert vom Typ T zurückgibt. Verwenden Sie Task, wenn die abgeschlossene Methode keinen sinnvollen Wert zurückgibt.In other cases, you use Task(T) if the completed method has a return statement that returns a value of type T, and you use Task if the completed method doesn’t return a meaningful value. Sie können sich den Task-Rückgabetyp wie „Task(void)“ vorstellen.You can think of the Task return type as meaning "Task(void)."

    Weitere Informationen finden Sie unter Async Return Types (C#) (Asynchrone Rückgabetypen (C#)).For more information, see Async Return Types (C#).

    Die Methode GetURLContents verfügt über eine return-Anweisung, und die Anweisung gibt ein Bytearray zurück.Method GetURLContents has a return statement, and the statement returns a byte array. Daher ist der Rückgabetyp der der asynchronen Version „Task(T)“, wobei „T“ ein Bytearray ist.Therefore, the return type of the async version is Task(T), where T is a byte array. Nehmen Sie folgende Änderungen in der Methodensignatur vor:Make the following changes in the method signature:

    • Ändern Sie den Rückgabetyp zu Task<byte[]>.Change the return type to Task<byte[]>.

    • Asynchrone Methoden verfügen gemäß der Konvention über Namen, die auf „Async“ enden. Benennen Sie also die Methode GetURLContentsAsync um.By convention, asynchronous methods have names that end in "Async," so rename the method GetURLContentsAsync.

    Im folgenden Code sind diese Änderungen dargestellt.The following code shows these changes.

    private async Task<byte[]> GetURLContentsAsync(string url)  
    

    Mit diesen wenigen Änderungen ist die Konvertierung von GetURLContents zu einer asynchronen Methode abgeschlossen.With those few changes, the conversion of GetURLContents to an asynchronous method is complete.

So konvertieren Sie „SumPageSizes“ in eine asynchrone MethodeTo convert SumPageSizes to an asynchronous method

  1. Wiederholen Sie die Schritte des vorherigen Verfahrens für SumPageSizes.Repeat the steps from the previous procedure for SumPageSizes. Ändern Sie zunächst den Aufruf von GetURLContents zu einem asynchronen Aufruf.First, change the call to GetURLContents to an asynchronous call.

    • Ändern Sie den Namen der Methode, die aufgerufen wird, von GetURLContents zu GetURLContentsAsync, sofern Sie dies nicht bereits getan haben.Change the name of the method that’s called from GetURLContents to GetURLContentsAsync, if you haven't already done so.

    • Wenden Sie await auf die Aufgabe an, die durch GetURLContentsAsync zurückgegeben wird, um den Bytearraywert abzurufen.Apply await to the task that GetURLContentsAsync returns to obtain the byte array value.

    Im folgenden Code sind diese Änderungen dargestellt.The following code shows these changes.

    byte[] urlContents = await GetURLContentsAsync(url);  
    

    Die vorherige Zuweisung kürzt die folgenden zwei Codezeilen.The previous assignment abbreviates the following two lines of code.

    // 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 folgende Änderungen in der Methodensignatur vor:Make the following changes in the method's signature:

    • Markieren Sie die Methode mit dem Modifizierer async.Mark the method with the async modifier.

    • Fügen Sie dem Methodennamen „Async“ hinzu.Add "Async" to the method name.

    • Es ist dieses Mal keine Aufgabenrückgabevariable „T“ vorhanden, da SumPageSizesAsync keinen Wert für „T“ zurückgibt. (Die Methode weist keine return-Anweisung auf.) Die Methode muss jedoch eine Task zurückgeben, die awaitable ist.There is no task return variable, T, this time because SumPageSizesAsync doesn’t return a value for T. (The method has no return statement.) However, the method must return a Task to be awaitable. Ändern Sie daher den Rückgabetyp der Methode von void in Task.Therefore, change the return type of the method from void to Task.

    Im folgenden Code sind diese Änderungen dargestellt.The following code shows these changes.

    private async Task SumPageSizesAsync()  
    

    Die Konvertierung von SumPageSizes zu SumPageSizesAsync ist abgeschlossen.The conversion of SumPageSizes to SumPageSizesAsync is complete.

So konvertieren Sie „startButton_Click“ in eine asynchrone MethodeTo convert startButton_Click to an asynchronous method

  1. Ändern Sie im Ereignishandler den Namen der aufgerufenen Methode von SumPageSizes zu SumPageSizesAsync, sofern Sie dies nicht bereits vorgenommen haben.In the event handler, change the name of the called method from SumPageSizes to SumPageSizesAsync, if you haven’t already done so.

  2. Da es sich bei SumPageSizesAsync um eine asynchrone Methode handelt, ändern Sie den Code im Ereignishandler, um auf das Ergebnis zu warten.Because SumPageSizesAsync is an async method, change the code in the event handler to await the result.

    Der Aufruf von SumPageSizesAsync spiegelt den Aufruf von CopyToAsync in GetURLContentsAsync wider.The call to SumPageSizesAsync mirrors the call to CopyToAsync in GetURLContentsAsync. Der Aufruf gibt eine Task und keine Task(T) zurück.The call returns a Task, not a Task(T).

    Analog zu den vorherigen Vorgehensweisen können Sie den Aufruf mithilfe von einer oder zwei Anweisungen konvertieren.As in previous procedures, you can convert the call by using one statement or two statements. Im folgenden Code sind diese Änderungen dargestellt.The following code shows these changes.

    // One-step async call.  
    await SumPageSizesAsync();  
    
    // Two-step async call.  
    //Task sumTask = SumPageSizesAsync();  
    //await sumTask;  
    
  3. Um den versehentlichen Neustart des Vorgangs zu verhindern, fügen Sie oben in startButton_Click die folgende Anweisung ein, um die Schaltfläche Start zu deaktivieren.To prevent accidentally reentering the operation, add the following statement at the top of startButton_Click to disable the Start button.

    // Disable the button until the operation is complete.  
    startButton.IsEnabled = false;  
    

    Sie können die Schaltfläche am Ende des Ereignishandlers wieder aktivieren.You can reenable the button at the end of the event handler.

    // Reenable the button in case you want to run the operation again.  
    startButton.IsEnabled = true;  
    

    Weitere Informationen zum erneuten Eintreten finden Sie unter Handling Reentrancy in Async Apps (C#) (Ablauf des erneuten Eintretens in asynchronen Anwendungen (C#)).For more information about reentrancy, see Handling Reentrancy in Async Apps (C#).

  4. Fügen Sie der Deklaration abschließend den Modifizierer async hinzu, sodass der Ereignishandler auf SumPagSizesAsync warten kann.Finally, add the async modifier to the declaration so that the event handler can await SumPagSizesAsync.

    private async void startButton_Click(object sender, RoutedEventArgs e)  
    

    In der Regel werden die Namen der Ereignishandler nicht geändert.Typically, the names of event handlers aren’t changed. Der Rückgabetyp wird nicht zu Task geändert, da Ereignishandler void zurückgeben müssen.The return type isn’t changed to Task because event handlers must return void.

    Die Konvertierung des Projekts von der synchronen zu asynchronen Verarbeitung ist abgeschlossen.The conversion of the project from synchronous to asynchronous processing is complete.

So testen Sie die asynchrone LösungTo test the asynchronous solution

  1. Drücken Sie die Taste F5, um das Programm auszuführen, und klicken Sie dann auf die Schaltfläche Starten .Choose the F5 key to run the program, and then choose the Start button.

  2. Es sollte eine Ausgabe angezeigt werden, die der Ausgabe der synchronen Lösung gleicht.Output that resembles the output of the synchronous solution should appear. Folgende Unterschiede sind jedoch zu berücksichtigen.However, notice the following differences.

    • Die Ergebnisse treten nicht alle gleichzeitig auf, nachdem die Verarbeitung abgeschlossen wurde.The results don’t all occur at the same time, after the processing is complete. Beispielsweise enthalten beide Programme eine Zeile in startButton_Click, die das Textfeld löscht.For example, both programs contain a line in startButton_Click that clears the text box. 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.The intent is to clear the text box between runs if you choose the Start button for a second time, after one set of results has appeared. 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 the synchronous version, the text box is cleared just before the counts appear for the second time, when the downloads are completed and the UI thread is free to do other work. In der asynchronen Version wird das Textfeld unmittelbar gelöscht, nachdem Sie die Schaltfläche Start ausgewählt haben.In the asynchronous version, the text box clears immediately after you choose the Start button.

    • Das Wichtigste ist jedoch, dass der UI-Thread nicht blockiert wird, während Downloads vorgenommen werden.Most importantly, the UI thread isn’t blocked during the downloads. Sie können das Fenster verschieben oder dessen Größe anpassen, während die Webressourcen heruntergeladen, gezählt und angezeigt werden.You can move or resize the window while the web resources are being downloaded, counted, and displayed. 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.If one of the websites is slow or not responding, you can cancel the operation by choosing the Close button (the x in the red field in the upper-right corner).

So ersetzen Sie die Methode „GetURLContentsAsync“ durch eine .NET Framework-MethodeTo replace method GetURLContentsAsync with a .NET Framework method

  1. .NET Framework 4.5 bietet viele asynchrone Methoden, die Sie verwenden können.The .NET Framework 4.5 provides many async methods that you can use. Eine davon, die HttpClient-Methode GetByteArrayAsync(String) erfüllt genau das, was in dieser exemplarischen Vorgehensweise nötig ist.One of them, the HttpClient method GetByteArrayAsync(String), does just what you need for this walkthrough. Sie können sie anstelle der GetURLContentsAsync-Methode verwenden, die Sie in einer vorherigen Vorgehensweise erstellt haben.You can use it instead of the GetURLContentsAsync method that you created in an earlier procedure.

    Der erste Schritt besteht darin, ein HttpClient-Objekt in der Methode SumPageSizesAsync zu erstellen.The first step is to create an HttpClient object in method SumPageSizesAsync. Fügen Sie am Anfang der Methode die folgende Deklaration hinzu.Add the following declaration at the start of the method.

    // Declare an HttpClient object and increase the buffer size. The  
    // default buffer size is 65,536.  
    HttpClient client =  
        new HttpClient() { MaxResponseContentBufferSize = 1000000 };  
    
  2. Ersetzen Sie in SumPageSizesAsync, den Aufruf zu Ihrer GetURLContentsAsync-Methode durch einen Aufruf zur Methode HttpClient.In SumPageSizesAsync, replace the call to your GetURLContentsAsync method with a call to the HttpClient method.

    byte[] urlContents = await client.GetByteArrayAsync(url);  
    
  3. Entfernen Sie die von Ihnen geschriebene GetURLContentsAsync-Methode, oder kommentieren Sie sie aus.Remove or comment out the GetURLContentsAsync method that you wrote.

  4. Drücken Sie die Taste F5, um das Programm auszuführen, und klicken Sie dann auf die Schaltfläche Starten .Choose the F5 key to run the program, and then choose the Start button.

    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.The behavior of this version of the project should match the behavior that the "To test the asynchronous solution" procedure describes but with even less effort from you.

BeispielExample

Der folgende Code enthält das vollständige Beispiel der Konvertierung von einer synchronen zu einer asynchronen Lösung mithilfe der von Ihnen geschriebenen asynchronen GetURLContentsAsync-Methode.The following code contains the full example of the conversion from a synchronous to an asynchronous solution by using the asynchronous GetURLContentsAsync method that you wrote. Beachten Sie, dass sie der ursprünglichen synchronen Lösung sehr stark ähnelt.Notice that it strongly resembles the original, synchronous solution.

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/library/hh290136.aspx",  
                "http://msdn.microsoft.com/library/ee256749.aspx",  
                "http://msdn.microsoft.com/library/hh290138.aspx",  
                "http://msdn.microsoft.com/library/hh290140.aspx",  
                "http://msdn.microsoft.com/library/dd470362.aspx",  
                "http://msdn.microsoft.com/library/aa578028.aspx",  
                "http://msdn.microsoft.com/library/ms404677.aspx",  
                "http://msdn.microsoft.com/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 umfasst das vollständige Beispiel der Lösung, die die HttpClient-Methode GetByteArrayAsync verwendet.The following code contains the full example of the solution that uses the HttpClient method, GetByteArrayAsync.

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/library/hh290136.aspx",  
                "http://msdn.microsoft.com/library/ee256749.aspx",  
                "http://msdn.microsoft.com/library/hh290138.aspx",  
                "http://msdn.microsoft.com/library/hh290140.aspx",  
                "http://msdn.microsoft.com/library/dd470362.aspx",  
                "http://msdn.microsoft.com/library/aa578028.aspx",  
                "http://msdn.microsoft.com/library/ms404677.aspx",  
                "http://msdn.microsoft.com/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 auchSee Also

Async Sample: Accessing the Web Walkthrough (C# and Visual Basic) (Asynchrones Beispiel: Webzugriff – Exemplarische Vorgehensweise (C# und Visual Basic))Async Sample: Accessing the Web Walkthrough (C# and Visual Basic)
asyncasync
awaitawait
Asynchronous Programming with async and await (C#) (Asynchrone Programmierung mit Async und Await (C#))Asynchronous Programming with async and await (C#)
Asynchrone Rückgabetypen (C#)Async Return Types (C#)
Task-based Asynchronous Programming (TAP) (Aufgabenbasiertes asynchrones Programmieren (TAP))Task-based Asynchronous Programming (TAP)
Vorgehensweise: Erweitern der asynchronen exemplarischen Vorgehensweise mit Task.WhenAll (C#)How to: Extend the async Walkthrough by Using Task.WhenAll (C#)
Gewusst wie: Paralleles Erstellen mehrerer Webanforderungen mit „async“ und „await“ (C#)How to: Make Multiple Web Requests in Parallel by Using async and await (C#)