Porady: rozszerzanie wskazówek asynchronicznych za pomocą Task.WhenAll (C# i Visual Basic)
Można poprawić wydajność rozwiązania asynchronicznego w Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic) przez zastosowanie metody Task.WhenAll .Ta metoda asynchronicznie czeka na wiele operacji asynchronicznych, które są reprezentowane jako kolekcje zadań.
Można zauważyć w instruktażu, że witryny sieci Web będą pobierane w różnym tempie.Czasami jedna z witryn sieci web działa bardzo powoli, co opóźnia wszystkie pozostałe pobrania.Po uruchomieniu asynchronicznych rozwiązań, które kompilujesz w instruktażu, można łatwo zakończyć program, jeśli nie chcesz czekać, ale lepszym rozwiązaniem byłoby uruchomienie wszystkich plików do pobrania w tym samym czasie i pozwolenie na szybsze pobieranie bez oczekiwania na opóźnione elementy.
Należy stosować metodę Task.WhenAll do kolekcji zadań.Zastosowanie metody WhenAll powoduje zwrócenie pojedynczego zadania, które nie zostanie ukończone, aż do ukończenia wszystkich zadań w kolekcji.Wydaje się, że zadania działają równolegle, ale żadne dodatkowe wątki nie są tworzone.Zadania można wykonywać w dowolnej kolejności.
![]() |
---|
Poniższe procedury opisują rozszerzenia aplikacji asynchronicznych utworzonych za pomocą procedury opisanej w artykule Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic).Można opracować aplikacje bądź to przechodząc przez ścieżkę bądź ściągając kod z Developer Code Samples. Aby uruchomić przykład, na komputerze musisz mieć zainstalowane programy Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows Desktop, Visual Studio Express 2013 for Windows lub .NET Framework w wersji 4.5 lub 4.5.1. |
Aby dodać Task.WhenAll do rozwiązania GetURLContentsAsync
Dodaj metodę ProcessURLAsync do pierwszego wniosku opracowywanego w Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic).
Jeśli pobrano kod ze strony Przykłady kodu dla deweloperów, otwórz projekt AsyncWalkthrough, a następnie dodaj element ProcessURLAsync w pliku MainWindow.xaml.vb lub MainWindow.xaml.cs.
Jeśli kod jest opracowany przez wykonanie kroków przewodnika, dodaj metodę ProcessURLAsync do aplikacji, która obejmuje metodę GetURLContentsAsync.Plik MainWindow.xaml.vb lub MainWindow.xaml.cs dla tej aplikacji to pierwszy przykład w sekcji „Przykłady pełnego kodu z przewodnika”.
Metoda ProcessURLAsync konsoliduje akcje w treści pętli For Each lub foreach w metodzie SumPageSizesAsync w oryginalnym przewodniku.Metoda asynchronicznie pobiera zawartość określonej witryny sieci web jako tablicę bajtową, a następnie wyświetla i zwraca długość tej tablicy bajtowej.
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; }
Skomentuj lub usuń pętlę For Each lub foreach w SumPageSizesAsync, jak ukazuje poniższy kod.
'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; //}
Utwórz kolekcję zadań.Poniższy kod definiuje zapytanie, które podczas wykonywania przez metodę ToArray``1, tworzy kolekcję zadań pobierania zawartości każdej witryny sieci web.Zadania zostaną uruchomione po uzyskaniu wyniku zapytania.
Dodaj następujący kod do metody SumPageSizesAsync po zadeklarowaniu urlList.
' 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();
Zastosuj Task.WhenAll do kolekcji zadań, downloadTasks.Metoda Task.WhenAll zwraca pojedyncze zadanie, które kończy się wraz z ukończeniem wszystkich zadań w kolekcji.
W poniższym przykładzie Await lub await wyrażenie czeka na zakończenie pojedynczego zadania, które WhenAll zwraca.Wyrażenie daje w wyniku tablicę liczb całkowitych, gdzie każda liczba całkowita jest długością pobranej witryny sieci web.Dodaj następujący kod do SumPageSizesAsync, zaraz za kodem dodanym w poprzednim kroku.
' 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;
Na koniec użyj metody Sum w celu obliczenia sumy długości wszystkich witryn sieci Web.Dodaj następujący wiersz do SumPageSizesAsync.
Dim total = lengths.Sum()
int total = lengths.Sum();
Aby dodać Task.WhenAll do rozwiązania HttpClient.GetByteArrayAsync
Dodaj następującą wersję ProcessURLAsync do drugiej aplikacji opracowywanej w Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic).
Jeśli pobrano kod ze strony Przykłady kodu dla deweloperów, otwórz projekt AsyncWalkthrough_HttpClient, a następnie dodaj element ProcessURLAsync w pliku MainWindow.xaml.vb lub MainWindow.xaml.cs.
Jeśli kod jest opracowany przez wykonanie kroków przewodnika, dodaj metodę ProcessURLAsync do aplikacji, która używa metody HttpClient.GetByteArrayAsync.Plik MainWindow.xaml.vb lub MainWindow.xaml.cs dla tej aplikacji to drugi przykład w sekcji „Przykłady pełnego kodu z przewodnika”.
Metoda ProcessURLAsync konsoliduje akcje w treści pętli For Each lub foreach w metodzie SumPageSizesAsync w oryginalnym przewodniku.Metoda asynchronicznie pobiera zawartość określonej witryny sieci web jako tablicę bajtową, a następnie wyświetla i zwraca długość tej tablicy bajtowej.
Jedyną różnicą między metodą ProcessURLAsync w poprzedniej procedurze jest użycie wystąpienia obiektu 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; }
Skomentuj lub usuń pętlę For Each lub foreach w SumPageSizesAsync, jak ukazuje poniższy kod.
'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; //}
Definiuj zapytanie, które realizowane przez metodę ToArray``1, tworzy kolekcję zadań pobierających zawartość każdej witryny sieci Web.Zadania zostaną uruchomione po uzyskaniu wyniku zapytania.
Dodaj następujący kod do metody SumPageSizesAsync po zadeklarowaniu client i urlList.
' 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();
Następnie zastosuj Task.WhenAll do kolekcji zadań, downloadTasks.Metoda Task.WhenAll zwraca pojedyncze zadanie, które kończy się wraz z ukończeniem wszystkich zadań w kolekcji.
W poniższym przykładzie Await lub await wyrażenie czeka na zakończenie pojedynczego zadania, które WhenAll zwraca.Po ukończeniu wyrażenie Await lub await daje w wyniku tablicę liczb całkowitych, gdzie każda liczba całkowita jest długością pobranej witryny sieci web.Dodaj następujący kod do SumPageSizesAsync, zaraz za kodem dodanym w poprzednim kroku.
' 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;
Na koniec użyj metody Sum w celu uzyskania sumy długości wszystkich witryn sieci Web.Dodaj następujący wiersz do SumPageSizesAsync.
Dim total = lengths.Sum()
int total = lengths.Sum();
Aby przetestować rozwiązania Task.WhenAll
- Dla dowolnego z rozwiązań, wybierz klawisz F5, aby uruchomić program, a następnie wybierz przycisk Start.Dane wyjściowe powinny być podobne do danych wyjściowych z rozwiązań asynchronicznych w artykule Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic).Jednak zauważ, że witryny sieci Web pojawią w innej kolejności każdorazowo.
Przykład
Poniższy kod przedstawia rozszerzenia projektu, który używa metody GetURLContentsAsync do pobierania zawartości z sieci web.
' 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);
}
}
}
Poniższy kod przedstawia rozszerzenia projektu, który używa metody HttpClient.GetByteArrayAsync do pobierania zawartości z sieci web.
' 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);
}
}
}
Zobacz też
Zadania
Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic)