Porady: równoległe tworzenie wielu żądań internetowych przy użyciu Async i Await (Visual Basic)

W metodzie asynchronicznej zadania są uruchamiane po ich utworzeniu. Operator Await jest stosowany do zadania w punkcie w metodzie, w której przetwarzanie nie może być kontynuowane do momentu zakończenia zadania. Często zadanie jest oczekiwane natychmiast po jego utworzeniu, jak pokazano w poniższym przykładzie.

Dim result = Await someWebAccessMethodAsync(url)

Można jednak oddzielić tworzenie zadania od oczekiwania na zadanie, jeśli program ma inną pracę do wykonania, która nie zależy od ukończenia zadania.

' 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

Między uruchomieniem zadania i oczekiwaniem na nie można uruchomić inne zadania. Dodatkowe zadania są uruchamiane równolegle, ale nie są tworzone żadne dodatkowe wątki.

Poniższy program uruchamia trzy asynchroniczne pliki do pobrania w Internecie, a następnie oczekuje na nie w kolejności, w której są wywoływane. Zwróć uwagę, że po uruchomieniu programu zadania nie zawsze kończą się w kolejności, w której są tworzone i oczekiwane. Zaczynają działać po ich utworzeniu, a co najmniej jedno zadanie może zakończyć się przed osiągnięciem wyrażeń await przez metodę .

Uwaga

Aby ukończyć ten projekt, na komputerze musi być zainstalowany program Visual Studio 2012 lub nowszy oraz program .NET Framework 4.5 lub nowszy.

Aby zapoznać się z innym przykładem, który uruchamia wiele zadań w tym samym czasie, zobacz How to: Extend thesync Walkthrough by Using Task.WhenAll (Visual Basic)( Jak rozszerzyć przewodnik asynchroniczny przy użyciu task.WhenAll (Visual Basic).

Możesz pobrać kod dla tego przykładu z sekcji Przykłady kodu dla deweloperów.

Aby skonfigurować projekt

  1. Aby skonfigurować aplikację WPF, wykonaj następujące kroki. Szczegółowe instrukcje można znaleźć w temacie Przewodnik: uzyskiwanie dostępu do sieci Web przy użyciu Async i Await (Visual Basic).

    • Utwórz aplikację WPF zawierającą pole tekstowe i przycisk. Nadaj przyciskowi startButtonnazwę i nadaj nazwę polu resultsTextBoxtekstowego .

    • Dodaj odwołanie dla elementu System.Net.Http.

    • W pliku MainWindow.xaml.vb dodaj instrukcję Imports dla elementu System.Net.Http.

Aby dodać kod

  1. W oknie projektowania MainWindow.xaml kliknij dwukrotnie przycisk, aby utworzyć procedurę startButton_Click obsługi zdarzeń w MainWindow.xaml.vb.

  2. Skopiuj poniższy kod i wklej go do treści startButton_Click pliku w MainWindow.xaml.vb.

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

    Kod wywołuje metodę asynchroniczną , CreateMultipleTasksAsyncktóra napędza aplikację.

  3. Dodaj następujące metody obsługi do projektu:

    • ProcessURLAsyncHttpClient Metoda używa metody do pobrania zawartości witryny internetowej jako tablicy bajtów. Metoda obsługi, ProcessURLAsync a następnie wyświetla i zwraca długość tablicy.

    • DisplayResults wyświetla liczbę bajtów w tablicy bajtów dla każdego adresu URL. Ten ekran jest wyświetlany po zakończeniu pobierania każdego zadania.

    Skopiuj następujące metody i wklej je po procedurze startButton_Click obsługi zdarzeń w 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. Na koniec zdefiniuj metodę CreateMultipleTasksAsync, która wykonuje następujące kroki.

    • Metoda deklaruje HttpClient obiekt, do którego należy uzyskać dostęp w metodzie GetByteArrayAsync .ProcessURLAsync

    • Metoda tworzy i uruchamia trzy zadania typu Task<TResult>, gdzie TResult jest liczbą całkowitą. Po zakończeniu DisplayResults każdego zadania wyświetla adres URL zadania i długość pobranej zawartości. Ponieważ zadania są uruchamiane asynchronicznie, kolejność wyświetlania wyników może różnić się od kolejności, w jakiej zostały zadeklarowane.

    • Metoda oczekuje na ukończenie każdego zadania. Każdy Await operator zawiesza wykonywanie CreateMultipleTasksAsync do momentu zakończenia oczekiwanego zadania. Operator pobiera również wartość zwracaną z wywołania do ProcessURLAsync z każdego ukończonego zadania.

    • Po zakończeniu zadań i pobraniu wartości całkowitych metoda sumuje długości witryn internetowych i wyświetla wynik.

    Skopiuj następującą metodę i wklej ją do rozwiązania.

    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. Wybierz klawisz F5, aby uruchomić program, a następnie wybierz przycisk Uruchom .

    Uruchom program kilka razy, aby sprawdzić, czy trzy zadania nie zawsze kończą się w tej samej kolejności i że kolejność ich zakończenia nie musi być kolejnością, w której są tworzone i oczekiwane.

Przykład

Poniższy kod zawiera pełny przykład.

' 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

Zobacz też