Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Вы можете повысить производительность асинхронного решения в пошаговом руководстве, Доступ к Интернету с помощью Async и Await (Visual Basic) с помощью Task.WhenAll метода. Этот метод асинхронно ожидает несколько асинхронных операций, которые представлены в виде коллекции задач.
Возможно, вы заметили в пошаговом руководстве, что веб-сайты скачиваются по разным тарифам. Иногда один из веб-сайтов очень медленный, который задерживает все оставшиеся загрузки. При запуске асинхронных решений, которые вы создаете в пошаговом руководстве, вы можете легко завершить программу, если вы не хотите ждать, но лучше всего запустить все загрузки одновременно и позволить более быстрым загрузкам продолжаться без ожидания тех, которые задерживаются.
Вы применяете метод Task.WhenAll к коллекции задач. Использование WhenAll возвращает одну задачу, которая не будет завершена до тех пор, пока не завершится каждая задача в коллекции. Задачи, как представляется, выполняются параллельно, но дополнительные потоки не создаются. Задачи могут выполняться в любом порядке.
Это важно
В следующих процедурах описываются расширения для асинхронных приложений, разработанных в пошаговом руководстве. Доступ к Интернету с помощью Async и Await (Visual Basic). Вы можете разрабатывать приложения, выполнив пошаговое руководство или скачав пример из браузера .NET Sample Browser. Пример кода находится в проекте SerialAsyncExample .
Чтобы запустить пример, на компьютере должна быть установлена Visual Studio 2012 или более поздняя версия.
Добавление Task.WhenAll в решение GetURLContentsAsync
ProcessURLAsyncДобавьте метод в первое приложение, разработанное в пошаговом руководстве. Доступ к Интернету с помощью Async и Await (Visual Basic).Если вы скачали код из примеров кода разработчика, откройте проект AsyncWalkthrough, а затем добавьте
ProcessURLAsyncв файл MainWindow.xaml.vb.Если вы разработали код, выполнив пошаговое руководство, добавьте
ProcessURLAsyncв приложение, которое включает методGetURLContentsAsync. Файл MainWindow.xaml.vb для этого приложения является первым примером в разделе "Полные примеры кода из пошагового руководства".
Метод
ProcessURLAsyncобъединяет действия в текстеFor Eachцикла вSumPageSizesAsyncисходном пошаговом руководстве. Метод асинхронно загружает содержимое указанного веб-сайта в виде массива байтов, а затем отображает и возвращает длину массива байтов.Private Async Function ProcessURLAsync(url As String) As Task(Of Integer) Dim byteArray = Await GetURLContentsAsync(url) DisplayResults(url, byteArray) Return byteArray.Length End FunctionЗакомментируйте или удалите цикл
For EachвSumPageSizesAsync, как показано в следующем коде.'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Создайте коллекцию задач. Следующий код определяет запрос , который при выполнении методом ToArray создает коллекцию задач, скачивающих содержимое каждого веб-сайта. Задачи запускаются при оценке запроса.
Добавьте следующий код в метод
SumPageSizesAsyncпосле объявления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()Примените
Task.WhenAllк коллекции задач,downloadTasks.Task.WhenAllвозвращает одну задачу, завершающую выполнение всех задач в коллекции задач.В следующем примере выражение
Awaitожидает завершения единственной задачи, которую возвращаетWhenAll. Выражение вычисляет массив целых чисел, где каждое целое число — длина скачаемого веб-сайта. Добавьте следующий код сразу после добавления кода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Наконец, используйте Sum метод для вычисления суммы длины всех веб-сайтов. Добавьте следующую строку в
SumPageSizesAsync.Dim total = lengths.Sum()
Чтобы добавить Task.WhenAll к решению HttpClient.GetByteArrayAsync
Добавьте следующую версию
ProcessURLAsyncко второму приложению, которое разработано в Пошаговом руководстве: доступ к Интернету с помощью Async и Await (Visual Basic).Если вы скачали код из примеров кода разработчика, откройте проект AsyncWalkthrough_HttpClient, а затем добавьте
ProcessURLAsyncв файл MainWindow.xaml.vb.Если вы разработали код, выполнив пошаговое руководство, добавьте
ProcessURLAsyncв приложение, использующееHttpClient.GetByteArrayAsyncметод. Файл MainWindow.xaml.vb для этого приложения является вторым примером в разделе "Полные примеры кода из пошагового руководства".
Метод
ProcessURLAsyncобъединяет действия в текстеFor Eachцикла вSumPageSizesAsyncисходном пошаговом руководстве. Метод асинхронно загружает содержимое указанного веб-сайта в виде массива байтов, а затем отображает и возвращает длину массива байтов.Единственное отличие от
ProcessURLAsyncметода в предыдущей процедуре — использование экземпляра HttpClientclient.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Закомментируйте или удалите цикл
For EachвSumPageSizesAsync, как показано в следующем коде.'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Определите запрос , который при выполнении методом ToArray создает коллекцию задач, скачивающих содержимое каждого веб-сайта. Задачи запускаются при оценке запроса.
Добавьте следующий код в метод
SumPageSizesAsyncпосле объявленияclientи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()Затем примените
Task.WhenAllк коллекции задач.downloadTasksTask.WhenAllвозвращает одну задачу, завершающую выполнение всех задач в коллекции задач.В следующем примере выражение
Awaitожидает завершения единственной задачи, которую возвращаетWhenAll. По завершенииAwaitвыражение вычисляет массив целых чисел, из которых каждое — это длина загруженного веб-сайта. Добавьте следующий код сразу после добавления кода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Наконец, используйте Sum метод, чтобы получить сумму длины всех веб-сайтов. Добавьте следующую строку в
SumPageSizesAsync.Dim total = lengths.Sum()
Тестирование решений Task.WhenAll
Для любого решения нажмите клавишу F5, чтобы запустить программу, а затем нажмите кнопку "Пуск ". Выходные данные должны выглядеть как выходные данные из асинхронных решений в пошаговом руководстве. Доступ к Интернету с помощью Async и Await (Visual Basic). Однако обратите внимание, что веб-сайты отображаются в другом порядке каждый раз.
Пример 1
В следующем коде показаны расширения для проекта, использующего GetURLContentsAsync метод для скачивания содержимого из Интернета.
' 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
'NextNext
' 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/library/hh290136.aspx",
"https://msdn.microsoft.com/library/ee256749.aspx",
"https://msdn.microsoft.com/library/hh290138.aspx",
"https://msdn.microsoft.com/library/hh290140.aspx",
"https://msdn.microsoft.com/library/dd470362.aspx",
"https://msdn.microsoft.com/library/aa578028.aspx",
"https://msdn.microsoft.com/library/ms404677.aspx",
"https://msdn.microsoft.com/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 "https://".
Dim displayURL = url.Replace("https://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class
Пример 2
В следующем коде показаны расширения для проекта, использующего метод HttpClient.GetByteArrayAsync для скачивания содержимого из Интернета.
' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http
Imports System.Net
Imports System.IO
Class MainWindow
Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
resultsTextBox.Clear()
'' 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()
''<snippet7>
'Dim total = 0
'For Each url In urlList
' ' GetByteArrayAsync returns a task. At completion, the task
' ' produces a byte array.
' '<snippet31>
' Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
' '</snippet31>
' ' 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
'NextNext
' 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://www.msdn.com",
"https://msdn.microsoft.com/library/hh290136.aspx",
"https://msdn.microsoft.com/library/ee256749.aspx",
"https://msdn.microsoft.com/library/hh290138.aspx",
"https://msdn.microsoft.com/library/hh290140.aspx",
"https://msdn.microsoft.com/library/dd470362.aspx",
"https://msdn.microsoft.com/library/aa578028.aspx",
"https://msdn.microsoft.com/library/ms404677.aspx",
"https://msdn.microsoft.com/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 "https://".
Dim displayURL = url.Replace("https://", "")
resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
End Sub
End Class