Поделиться через


Как: Создать несколько веб-запросов параллельно, используя async и await (Visual Basic)

В асинхронном методе задачи запускаются при их создании. Оператор Await применяется к задаче в точке метода, где обработка не может продолжаться до завершения задачи. Часто задача ожидается сразу после ее создания, как показано в следующем примере.

Dim result = Await someWebAccessMethodAsync(url)

Однако вы можете отделить создание задачи от ожидания ее выполнения, если у вашей программы есть другие задачи, выполнение которых не зависит от завершения этой.

' The following line creates and starts the task.
Dim myTask = someWebAccessMethodAsync(url)

' While the task is running, you can do other work that does not depend
' on the results of the task.
' . . . . .

' The application of Await suspends the rest of this method until the task is
' complete.
Dim result = Await myTask

Между запуском задачи и ожиданием ее можно запустить другие задачи. Дополнительные задачи неявно выполняются параллельно, но дополнительные потоки не создаются.

Следующая программа запускает три асинхронных веб-загрузки, а затем ожидает их в том порядке, в котором они вызываются. Обратите внимание, что при запуске программы задачи не всегда завершаются в том порядке, в котором они созданы и ожидаются. Они начинают выполняться при создании, а одна или несколько задач могут завершиться, прежде чем метод достигнет выражений await.

Замечание

Чтобы завершить этот проект, необходимо установить Visual Studio 2012 или более поздней версии и .NET Framework 4.5 или более поздней версии на компьютере.

Другой пример, который запускает несколько задач одновременно, см. в разделе "Практическое руководство. Расширение асинхронного пошагового руководства с помощью task.WhenAll (Visual Basic)".

Вы можете скачать код для этого примера из примеров кода разработчика.

Настройка проекта

  1. Чтобы настроить приложение WPF, выполните следующие действия. Подробные инструкции см. в пошаговом руководстве. Доступ к Интернету с помощью Async и Await (Visual Basic).

    • Создайте приложение WPF, содержащее текстовое поле и кнопку. Назовите кнопку startButtonи назовите текстовое поле resultsTextBox.

    • Добавьте ссылку для System.Net.Http.

    • В файле MainWindow.xaml.vb добавьте инструкцию Imports для System.Net.Http.

Добавление кода

  1. В окне конструктора MainWindow.xaml дважды щёлкните на кнопку, чтобы создать обработчик событий startButton_Click в MainWindow.xaml.vb.

  2. Скопируйте следующий код и вставьте его в тело startButton_Click в MainWindow.xaml.vb.

    resultsTextBox.Clear()
    Await CreateMultipleTasksAsync()
    resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."
    

    Код вызывает асинхронный метод, CreateMultipleTasksAsyncкоторый управляет приложением.

  3. Добавьте в проект следующие методы поддержки:

    • ProcessURLAsync HttpClient использует метод для скачивания содержимого веб-сайта в виде массива байтов. Затем метод ProcessURLAsync поддержки отображает и возвращает длину массива.

    • DisplayResults отображает количество байтов в массиве байтов для каждого URL-адреса. На этом экране показано, когда каждая задача завершит загрузку.

    Скопируйте следующие методы и вставьте их после обработчика startButton_Click событий в MainWindow.xaml.vb.

    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
    
  4. Наконец, определите метод CreateMultipleTasksAsync, который выполняет следующие действия.

    • Метод объявляет объект HttpClient, к которому необходимо получить доступ для метода GetByteArrayAsync в ProcessURLAsync.

    • Метод создает и запускает три задачи типа Task<TResult>, где TResult является целое число. Как только завершается каждая задача, DisplayResults отображает URL-адрес задачи и длину загруженного содержимого. Так как задачи выполняются асинхронно, порядок отображения результатов может отличаться от порядка, в котором они были объявлены.

    • Метод ожидает завершения каждой задачи. Каждый Await оператор приостанавливает выполнение CreateMultipleTasksAsync до завершения ожидаемой задачи. Оператор также получает возвращаемое значение из вызова ProcessURLAsync из каждой завершенной задачи.

    • После завершения задач и получения целочисленных значений метод суммирует длину веб-сайтов и отображает результат.

    Скопируйте следующий метод и вставьте его в решение.

    Private Async Function CreateMultipleTasksAsync() 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}
    
        ' Create and start the tasks. As each task finishes, DisplayResults
        ' displays its length.
        Dim download1 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com", client)
        Dim download2 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/library/hh156528(VS.110).aspx", client)
        Dim download3 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/library/67w7t67f.aspx", client)
    
        ' Await each task.
        Dim length1 As Integer = Await download1
        Dim length2 As Integer = Await download2
        Dim length3 As Integer = Await download3
    
        Dim total As Integer = length1 + length2 + length3
    
        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    End Function
    
  5. Нажмите клавишу F5, чтобы запустить программу, а затем нажмите кнопку Start .

    Запустите программу несколько раз, чтобы убедиться, что три задачи не всегда заканчиваются в одном порядке, и порядок их завершения не обязательно является порядком их создания и ожидания.

Пример

Следующий код содержит полный пример.

' Add the following Imports statements, and add a reference for System.Net.Http.
Imports System.Net.Http

Class MainWindow

    Async Sub startButton_Click(sender As Object, e As RoutedEventArgs) Handles startButton.Click
        resultsTextBox.Clear()
        Await CreateMultipleTasksAsync()
        resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."
    End Sub

    Private Async Function CreateMultipleTasksAsync() 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}

        ' Create and start the tasks. As each task finishes, DisplayResults
        ' displays its length.
        Dim download1 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com", client)
        Dim download2 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/library/hh156528(VS.110).aspx", client)
        Dim download3 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/library/67w7t67f.aspx", client)

        ' Await each task.
        Dim length1 As Integer = Await download1
        Dim length2 As Integer = Await download2
        Dim length3 As Integer = Await download3

        Dim total As Integer = length1 + length2 + length3

        ' Display the total count for all of the websites.
        resultsTextBox.Text &= String.Format(vbCrLf & vbCrLf &
                                             "Total bytes returned:  {0}" & vbCrLf, total)
    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

См. также