Sdílet prostřednictvím


Postupy: Rozšíření návodu asynchronních úloh pomocí metody Task.WhenAll (C# and Visual Basic)

Můžete vylepšit výkon asynchronního řešení v Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic) pomocí metody Task.WhenAll.Tato metoda asynchronně čeká na více asynchronních operací, které jsou reprezentovány ve formě sad úkolů.

Pravděpodobně jste si všimli v návodu, že se weby stahují různými rychlostmi.Někdy jedna z webových stránek je velmi pomalá, což způsobuje zpoždění všech zbývajících stahování.Když spustíte asynchronní řešení, které vytvoříte v tomto návodu, můžete ukončit program snadno, pokud nechcete čekat, ale vhodnější by bylo začít všechna stahování současně a nechat pokračovat rychlejší stahování bez čekání na zpožděné stažení.

Použijte metodu Task.WhenAll u kolekce úkolů.Použití WhenAll vrátí jeden úkol, který není kompletní až do dokončení všech úloh v kolekci.Zdá se, že úkoly jsou spuštěny paralelně, ale žádná další vlákna nejsou vytvořena.Úkoly lze provést v libovolném pořadí.

Důležitá poznámkaDůležité

Následující postupy popisují rozšíření pro asynchronní aplikace, které jsou vyvíjeny v Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic).Můžete vyvíjet aplikace dokončením návodu nebo stažením kódu z ukázek kódu vývojáře.

Chcete-li spustit příklad, musíte mít nainstalovanou aplikaci Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows Desktop, Visual Studio Express 2013 for Windows nebo rozhraní .NET Framework 4.5 nebo 4.5.1 v počítači.

Přidání metody Task.WhenAll do řešení GetURLContentsAsync

  1. Přidejte metodu ProcessURLAsync do první aplikace, která je vytvořena v Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic).

    • Pokud jste stáhli kód z tématu Ukázky kódu vývojáře, otevřete projekt AsyncWalkthrough a přidejte metodu ProcessURLAsync do souboru MainWindow.xaml.vb nebo MainWindow.xaml.cs.

    • Pokud jste kód vyvinuli dokončením návodu, přidejte metodu ProcessURLAsync do aplikace, která obsahuje metodu GetURLContentsAsync.Soubor MainWindow.xaml.vb nebo MainWindow.xaml.cs pro tuto aplikaci je první příklad v části "Kompletní kód příkladů z návodu".

    Metoda ProcessURLAsync spojuje akce v těle smyčky For Each nebo foreach v SumPageSizesAsync v původním návodu.Metody asynchronně stáhnou obsah zadaného webu jako bajtové pole, a poté zobrazí a vrátí délku bajtového pole.

    Private Async Function ProcessURLAsync(url As String) As Task(Of Integer)
    
        Dim byteArray = Await GetURLContentsAsync(url)
        DisplayResults(url, byteArray)
        Return byteArray.Length
    End Function
    
    private async Task<int> ProcessURLAsync(string url)
    {
        var byteArray = await GetURLContentsAsync(url);
        DisplayResults(url, byteArray);
        return byteArray.Length;
    }
    
  2. Okomentujte nebo odstraňte smyčku For Each nebo foreach v rámci SumPageSizesAsync tak, jak ukazuje následující kód.

    '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
    
    //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; 
    //}
    
  3. Vytvořte kolekci úkolů.Následující kód definujte dotaz, který je spuštěn metodou ToArray``1 vytvoří kolekci úkolů, které stáhnou obsah každého webu.Úkoly jsou spuštěny, když je vyhodnocen dotaz.

    Po deklaraci urlList přidejte následující kód do metody SumPageSizesAsync.

    ' Create a query.  
    Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
        From url In urlList Select ProcessURLAsync(url)
    
    ' Use ToArray to execute the query and start the download tasks. 
    Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()
    
    // Create a query. 
    IEnumerable<Task<int>> downloadTasksQuery = 
        from url in urlList select ProcessURLAsync(url);
    
    // Use ToArray to execute the query and start the download tasks.
    Task<int>[] downloadTasks = downloadTasksQuery.ToArray();
    
  4. Použijte Task.WhenAll na kolekci úloh, downloadTasks.Task.WhenAll vrátí jeden úkol, který je dokončen v případě, že byly dokončeny všechny úkoly v kolekci úkolů.

    V následujícím příkladu výraz Await nebo await čeká na dokončení jedné úlohy, kterou vrátí metoda WhenAll.Výraz je vyhodnocen jako pole celých čísel, kde každé celé číslo je délka stahování webu.Za kód, který jste přidali v předchozím kroku, přidejte kód SumPageSizesAsync

    ' Await the completion of all the running tasks. 
    Dim lengths As Integer() = Await Task.WhenAll(downloadTasks)
    
    '' The previous line is equivalent to the following two statements. 
    'Dim whenAllTask As Task(Of Integer()) = Task.WhenAll(downloadTasks) 
    'Dim lengths As Integer() = Await whenAllTask
    
    // Await the completion of all the running tasks. 
    int[] lengths = await Task.WhenAll(downloadTasks);
    
    //// The previous line is equivalent to the following two statements. 
    //Task<int[]> whenAllTask = Task.WhenAll(downloadTasks); 
    //int[] lengths = await whenAllTask;
    
  5. Nakonec použijte metodu Sum pro výpočet součtu délek všech webových stránek.Přidejte následující řádek do SumPageSizesAsync.

    Dim total = lengths.Sum()
    
    int total = lengths.Sum();
    

Přidání metody Task.WhenAll do řešení HttpClient.GetByteArrayAsync

  1. Přidejte následující verzi ProcessURLAsync do druhé aplikace, která je vytvořena v Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic).

    • Pokud jste stáhli kód z tématu Ukázky kódu vývojáře, otevřete projekt AsyncWalkthrough_HttpClient a přidejte metodu ProcessURLAsync do souboru MainWindow.xaml.vb nebo MainWindow.xaml.cs.

    • Pokud jste kód vyvinuli dokončením návodu, přidejte metodu ProcessURLAsync do aplikace, která používá metodu HttpClient.GetByteArrayAsync.Soubor MainWindow.xaml.vb nebo MainWindow.xaml.cs pro tuto aplikaci je druhý příklad v části "Kompletní kód příkladů z návodu".

    Metoda ProcessURLAsync spojuje akce v těle smyčky For Each nebo foreach v SumPageSizesAsync v původním návodu.Metody asynchronně stáhnou obsah zadaného webu jako bajtové pole, a poté zobrazí a vrátí délku bajtového pole.

    Jediný rozdíl oproti metodě ProcessURLAsync v předchozím postupu je použití instance HttpClient, client.

    Private Async Function ProcessURLAsync(url As String, client As HttpClient) As Task(Of Integer)
    
        Dim byteArray = Await client.GetByteArrayAsync(url)
        DisplayResults(url, byteArray)
        Return byteArray.Length
    End Function
    
    async Task<int> ProcessURL(string url, HttpClient client)
    {
        byte[] byteArray = await client.GetByteArrayAsync(url);
        DisplayResults(url, byteArray);
        return byteArray.Length;
    }
    
  2. Okomentujte nebo odstraňte smyčku For Each nebo foreach v rámci SumPageSizesAsync tak, jak ukazuje následující kód.

    '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
    
    //var total = 0; 
    //foreach (var url in urlList) 
    //{ 
    //    // GetByteArrayAsync returns a Task<T>. At completion, the task 
    //    // produces a byte array. 
    //    byte[] urlContent = await client.GetByteArrayAsync(url); 
    
    //    // The previous line abbreviates the following two assignment 
    //    // statements. 
    //    Task<byte[]> getContentTask = client.GetByteArrayAsync(url); 
    //    byte[] urlContent = await getContentTask; 
    
    //    DisplayResults(url, urlContent); 
    
    //    // Update the total. 
    //    total += urlContent.Length; 
    //}
    
  3. Definujte dotaz, který při spuštění metodou ToArray``1 vytvoří kolekci úkolů, které stáhnou obsah každého webu.Úkoly jsou spuštěny, když je vyhodnocen dotaz.

    Po deklaraci client a urlList přidejte následující kód do metody SumPageSizesAsync.

    ' Create a query. 
    Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
        From url In urlList Select ProcessURLAsync(url, client)
    
    ' Use ToArray to execute the query and start the download tasks. 
    Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()
    
    // Create a query.
    IEnumerable<Task<int>> downloadTasksQuery = 
        from url in urlList select ProcessURL(url, client);
    
    // Use ToArray to execute the query and start the download tasks.
    Task<int>[] downloadTasks = downloadTasksQuery.ToArray();
    
  4. Dále použijte metodu Task.WhenAll na kolekci úloh, downloadTasks.Task.WhenAll vrátí jeden úkol, který je dokončen v případě, že byly dokončeny všechny úkoly v kolekci úkolů.

    V následujícím příkladu výraz Await nebo await čeká na dokončení jedné úlohy, kterou vrátí metoda WhenAll.Po dokončení je výraz Await nebo await vyhodnocen jako pole celých čísel, kde každé celé číslo je délka stahování webu.Za kód, který jste přidali v předchozím kroku, přidejte kód SumPageSizesAsync

    ' Await the completion of all the running tasks. 
    Dim lengths As Integer() = Await Task.WhenAll(downloadTasks)
    
    '' The previous line is equivalent to the following two statements. 
    'Dim whenAllTask As Task(Of Integer()) = Task.WhenAll(downloadTasks) 
    'Dim lengths As Integer() = Await whenAllTask
    
    // Await the completion of all the running tasks. 
    int[] lengths = await Task.WhenAll(downloadTasks);
    
    //// The previous line is equivalent to the following two statements. 
    //Task<int[]> whenAllTask = Task.WhenAll(downloadTasks); 
    //int[] lengths = await whenAllTask;
    
  5. Nakonec použijte metodu Sum pro získání součtu délek všech webových stránek.Přidejte následující řádek do SumPageSizesAsync.

    Dim total = lengths.Sum()
    
    int total = lengths.Sum();
    

Otestování řešení Task.WhenAll

Příklad

Následující kód ukazuje rozšíření pro projekt, který používá metodu GetURLContentsAsync ke stažení obsahu z webu.

' 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()

        ' 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." 
    End Sub 


    Private Async Function SumPageSizesAsync() As Task

        ' Make a list of web addresses. 
        Dim urlList As List(Of String) = SetUpURLList()

        ' Create a query.  
        Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
            From url In urlList Select ProcessURLAsync(url)

        ' Use ToArray to execute the query and start the download tasks. 
        Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()

        ' You can do other work here before awaiting. 

        ' Await the completion of all the running tasks. 
        Dim lengths As Integer() = Await Task.WhenAll(downloadTasks)

        '' The previous line is equivalent to the following two statements. 
        'Dim whenAllTask As Task(Of Integer()) = Task.WhenAll(downloadTasks) 
        'Dim lengths As Integer() = Await whenAllTask 

        Dim total = lengths.Sum()

        '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 web addresses.
        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",
                "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 


    ' The actions from the foreach loop are moved to this async method. 
    Private Async Function ProcessURLAsync(url As String) As Task(Of Integer)

        Dim byteArray = Await GetURLContentsAsync(url)
        DisplayResults(url, byteArray)
        Return byteArray.Length
    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()
            ' 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.   
                ' CopyToAsync returns a Task, not a Task<T>.
                Await responseStream.CopyToAsync(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 

End Class
// 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_WhenAll
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }


        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            resultsTextBox.Clear();

            // Two-step async call.
            Task sumTask = SumPageSizesAsync();
            await sumTask;

            // One-step async call. 
            //await SumPageSizesAsync();

            resultsTextBox.Text += "\r\nControl returned to startButton_Click.\r\n";
        }


        private async Task SumPageSizesAsync()
        {
            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();

            // Create a query. 
            IEnumerable<Task<int>> downloadTasksQuery = 
                from url in urlList select ProcessURLAsync(url);

            // Use ToArray to execute the query and start the download tasks.
            Task<int>[] downloadTasks = downloadTasksQuery.ToArray();

            // You can do other work here before awaiting. 

            // Await the completion of all the running tasks. 
            int[] lengths = await Task.WhenAll(downloadTasks);

            //// The previous line is equivalent to the following two statements. 
            //Task<int[]> whenAllTask = Task.WhenAll(downloadTasks); 
            //int[] lengths = await whenAllTask; 

            int total = lengths.Sum();

            //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",
                "https://msdn.microsoft.com/library/windows/apps/br211380.aspx",
                "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;
        }



        // The actions from the foreach loop are moved to this async method. 
        private async Task<int> ProcessURLAsync(string url)
        {
            var byteArray = await GetURLContentsAsync(url);
            DisplayResults(url, byteArray);
            return byteArray.Length;
        }


        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())
            {
                // Get the data stream that is associated with the specified url. 
                using (Stream responseStream = response.GetResponseStream())
                {
                    await responseStream.CopyToAsync(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);

        }
    }
}

Následující kód ukazuje rozšíření pro projekt, který používá metodu HttpClient.GetByteArrayAsync ke stažení obsahu z webu.

' 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()

        '' 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." 
    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()

        ' Create a query. 
        Dim downloadTasksQuery As IEnumerable(Of Task(Of Integer)) =
            From url In urlList Select ProcessURLAsync(url, client)

        ' Use ToArray to execute the query and start the download tasks. 
        Dim downloadTasks As Task(Of Integer)() = downloadTasksQuery.ToArray()

        ' You can do other work here before awaiting. 

        ' Await the completion of all the running tasks. 
        Dim lengths As Integer() = Await Task.WhenAll(downloadTasks)

        '' The previous line is equivalent to the following two statements. 
        'Dim whenAllTask As Task(Of Integer()) = Task.WhenAll(downloadTasks) 
        'Dim lengths As Integer() = Await whenAllTask 

        Dim total = lengths.Sum()

        '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 web addresses.
        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
            {
                "http://www.msdn.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 ProcessURLAsync(url As String, client As HttpClient) As Task(Of Integer)

        Dim byteArray = Await client.GetByteArrayAsync(url)
        DisplayResults(url, byteArray)
        Return byteArray.Length
    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
// 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_HttpClient_WhenAll
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            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";
        }


        private async Task SumPageSizesAsync()
        {
            // Make a list of web addresses.
            List<string> urlList = SetUpURLList();


            // Declare an HttpClient object and increase the buffer size. The 
            // default buffer size is 65,536.
            HttpClient client = new HttpClient() { MaxResponseContentBufferSize = 1000000 };

            // Create a query.
            IEnumerable<Task<int>> downloadTasksQuery = 
                from url in urlList select ProcessURL(url, client);

            // Use ToArray to execute the query and start the download tasks.
            Task<int>[] downloadTasks = downloadTasksQuery.ToArray();

            // You can do other work here before awaiting. 

            // Await the completion of all the running tasks. 
            int[] lengths = await Task.WhenAll(downloadTasks);

            //// The previous line is equivalent to the following two statements. 
            //Task<int[]> whenAllTask = Task.WhenAll(downloadTasks); 
            //int[] lengths = await whenAllTask; 

            int total = lengths.Sum();

            //var total = 0; 
            //foreach (var url in urlList) 
            //{ 
            //    // GetByteArrayAsync returns a Task<T>. At completion, the task 
            //    // produces a byte array. 
            //    byte[] urlContent = await client.GetByteArrayAsync(url); 

            //    // The previous line abbreviates the following two assignment 
            //    // statements. 
            //    Task<byte[]> getContentTask = client.GetByteArrayAsync(url); 
            //    byte[] urlContent = await getContentTask; 

            //    DisplayResults(url, urlContent); 

            //    // Update the total. 
            //    total += urlContent.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()
        {
            List<string> urls = new List<string> 
            { 
                "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;
        }


        // The actions from the foreach loop are moved to this async method.
        async Task<int> ProcessURL(string url, HttpClient client)
        {
            byte[] byteArray = await client.GetByteArrayAsync(url);
            DisplayResults(url, byteArray);
            return byteArray.Length;
        }


        private void DisplayResults(string url, byte[] content)
        {
            // Display the length of each web site. 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);
        }
    }
}

Viz také

Úkoly

Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic)

Referenční dokumentace

Task.WhenAll