Udostępnij za pośrednictwem


Porady: równoległe żądania sieci Web za pomocą Async i Await (C# i Visual Basic)

W metodzie asynchronicznej zadania są uruchamiane, gdy są one tworzone.Operator Await (Visual Basic) lub await (C#) jest stosowany do zadania w tym punkcie metody, w którym przetwarzanie nie może być kontynuowane, dopóki zadanie się nie zakończy.Często zadanie jest oczekiwany tak szybko, jak jest ono tworzony, jak w poniższym przykładzie.

Dim result = Await someWebAccessMethodAsync(url)
var result = await someWebAccessMethodAsync(url);

Jednakże można oddzielić tworzenie zadania od oczekiwania na zadanie, jeśli w programie trzeba wykonać inne prace, które nie są zależne od zakończenia tego 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
// The following line creates and starts the task.
var myTask = someWebAccessMethodAsync(url);

// While the task is running, you can do other work that doesn't depend
// on the results of the task.
// . . . . .

// The application of await suspends the rest of this method until the task is complete.
var result = await myTask;

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

Poniższy program uruchamia trzy asynchroniczne pobrania z sieci web, a następnie oczekuje na ich zakończenie w kolejności ich wywołania.Zwróć uwagę, że po uruchomieniu programu, który zadania nie są zawsze kończone w kolejności, w której są one tworzone i oczekiwane.Zaczynają działać z chwilą ich utworzenia i jedno lub więcej zadań może zakończyć się, zanim metoda osiągnie wyrażenie await.

[!UWAGA]

Aby wykonać ten projekt, 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 4.5 lub 4.5.1.

Aby uzyskać inny przykład, w którym uruchamia się kilka zadań w tym samym czasie, zobacz Porady: rozszerzanie wskazówek asynchronicznych za pomocą Task.WhenAll (C# i Visual Basic).

Możesz pobrać kod dla tego przykładu z Próbki kodu deweloperskiego.

Aby skonfigurować projekt

  • Aby skonfigurować aplikację programu WPF, wykonaj następujące czynności.Można znaleźć szczegółowe instrukcje tych kroków w Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic).

    • Tworzenie aplikacji WPF, która zawiera pole tekstowe i przycisk.Nazwij przycisk startButton i pole tekstowego resultsTextBox.

    • Dodaj odwołanie do System.Net.Http.

    • W pliku MainWindow.xaml.vb lub MainWindow.xaml.cs dodaj instrukcję Imports lub dyrektywę using w sekcji System.Net.Http.

Aby dodać kod

  1. W oknie projektu, MainWindow.xaml, kliknij dwukrotnie ten przycisk, aby utworzyć startButton_Click obsługi zdarzeń w MainWindow.xaml.vb lub MainWindow.xaml.cs.Alternatywnie, wybierz przycisk, wybierz ikonę Programy obsługi zdarzeń dla wybranych elementów w oknie Właściwości, a następnie wprowadź startButton_Click w polu tekstowym Kliknij.

  2. Kopiuj poniższy kod i wklej go w treść startButton_Click w MainWindow.xaml.vb lub MainWindow.xaml.cs.

    resultsTextBox.Clear()
    Await CreateMultipleTasksAsync()
    resultsTextBox.Text &= vbCrLf & "Control returned to button1_Click."
    
    resultsTextBox.Clear();
    await CreateMultipleTasksAsync();
    resultsTextBox.Text += "\r\n\r\nControl returned to startButton_Click.\r\n";
    

    Kod wywołuje metodę asynchroniczną, CreateMultipleTasksAsync, która steruje aplikacją.

  3. Dodaj następujące metody pomocy technicznej do projektu:

    • ProcessURLAsync używa HttpClient metody do pobierania zawartości witryny sieci Web w postaci tablicy bajtów.Następnie metoda pomocnicza ProcessURLAsync wyświetla i zwraca długość tablicy.

    • DisplayResults wyświetla liczbę bajtów w tablicy bajtowej dla każdego adresu URL.Te informacje są wyświetlane, gdy każde zadanie zakończy pobieranie.

    Kopiuj poniższe metody i wklej je za obiektem startButton_Click w MainWindow.xaml.vb lub MainWindow.xaml.cs.

    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
    
    async Task<int> ProcessURLAsync(string url, HttpClient client)
    {
        var byteArray = await client.GetByteArrayAsync(url);
        DisplayResults(url, byteArray);
        return byteArray.Length;
    }
    
    
    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);
    }
    
  4. Na koniec zdefiniuj metodę CreateMultipleTasksAsync, która spowoduje wykonanie następujących czynności.

    • Metoda deklaruje obiekt HttpClient, który jest potrzebny do uzyskania dostępu do metody GetByteArrayAsync w metodzie ProcessURLAsync.

    • Metoda tworzy i uruchamia trzy zadania typu Task, gdzie TResult jest liczbą całkowitą.Po zakończeniu każdego zadania DisplayResults wyświetla adres URL tego zadania i długość pobranej treści.Ponieważ zadania odbywają się asynchronicznie, kolejność, w jakiej są wyświetlane wyniki, może się różnić się od kolejności, w której zostały one zadeklarowane.

    • Metoda czeka na zakończenie każdego zadania.Każdy operator Await lub await wstrzymuje wykonywanie funkcji CreateMultipleTasksAsync, aż oczekiwane zadanie się zakończy.Operator pobiera również wartość zwracaną z wywołania metody ProcessURLAsync z każdego ukończonego zadania.

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

    Kopiuj następującą metodę i wkleić 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/en-us/library/hh156528(VS.110).aspx", client)
        Dim download3 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/en-us/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 Task CreateMultipleTasksAsync()
    {
        // Declare an HttpClient object, and increase the buffer size. The 
        // default buffer size is 65,536.
        HttpClient client =
            new HttpClient() { MaxResponseContentBufferSize = 1000000 };
    
        // Create and start the tasks. As each task finishes, DisplayResults  
        // displays its length.
        Task<int> download1 = 
            ProcessURLAsync("https://msdn.microsoft.com", client);
        Task<int> download2 = 
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/hh156528(VS.110).aspx", client);
        Task<int> download3 = 
            ProcessURLAsync("https://msdn.microsoft.com/en-us/library/67w7t67f.aspx", client);
    
        // Await each task. 
        int length1 = await download1;
        int length2 = await download2;
        int length3 = await download3;
    
        int total = length1 + length2 + length3;
    
        // Display the total count for the downloaded websites.
        resultsTextBox.Text +=
            string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
    }
    
  5. Wybierz klawisz F5, aby uruchomić program, a następnie wybierz przycisk Start.

    Uruchom program kilka razy, aby sprawdzić, czy te trzy zadania nie zawsze kończą się w tej samej kolejności i czy kolejność ich zakończenia niekoniecznie jest kolejnością, w której są one 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/en-us/library/hh156528(VS.110).aspx", client)
        Dim download3 As Task(Of Integer) =
            ProcessURLAsync("https://msdn.microsoft.com/en-us/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 "http://". 
        Dim displayURL = url.Replace("http://", "")
        resultsTextBox.Text &= String.Format(vbCrLf & "{0,-58} {1,8}", displayURL, bytes)
    End Sub 
End Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

// Add the following using directive, and add a reference for System.Net.Http. 
using System.Net.Http;


namespace AsyncExample_MultipleTasks
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private async void startButton_Click(object sender, RoutedEventArgs e)
        {
            resultsTextBox.Clear();
            await CreateMultipleTasksAsync();
            resultsTextBox.Text += "\r\n\r\nControl returned to startButton_Click.\r\n";
        }


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

            // Create and start the tasks. As each task finishes, DisplayResults  
            // displays its length.
            Task<int> download1 = 
                ProcessURLAsync("https://msdn.microsoft.com", client);
            Task<int> download2 = 
                ProcessURLAsync("https://msdn.microsoft.com/en-us/library/hh156528(VS.110).aspx", client);
            Task<int> download3 = 
                ProcessURLAsync("https://msdn.microsoft.com/en-us/library/67w7t67f.aspx", client);

            // Await each task. 
            int length1 = await download1;
            int length2 = await download2;
            int length3 = await download3;

            int total = length1 + length2 + length3;

            // Display the total count for the downloaded websites.
            resultsTextBox.Text +=
                string.Format("\r\n\r\nTotal bytes returned:  {0}\r\n", total);
        }


        async Task<int> ProcessURLAsync(string url, HttpClient client)
        {
            var byteArray = await client.GetByteArrayAsync(url);
            DisplayResults(url, byteArray);
            return byteArray.Length;
        }


        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);
        }
    }
}

Zobacz też

Zadania

Wskazówki: uzyskiwanie dostępu do sieci za pomocą Async i Await (C# i Visual Basic)

Porady: rozszerzanie wskazówek asynchronicznych za pomocą Task.WhenAll (C# i Visual Basic)

Koncepcje

Programowanie asynchroniczne z Async i Await (C# i Visual Basic)