共用方式為


如何:使用 Async 和 Await,同時發出多個 Web 要求 (C# 和 Visual Basic)

在非同步方法,工作會在建立時啟動。 等候 (Visual Basic) 或 等候 (C#) 運算子會在方法中無法繼續處理的點套用至工作,直到工作完成為止。 通常,當工作一建立時就會等候,如下列範例所示。

Dim result = Await someWebAccessMethodAsync(url)
var 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
// 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;

在開始工作和等候工作之間,您可以啟動其他工作。 其他工作會以隱含方式平行執行,但是不會建立其他執行緒。

下列程式啟動三個非同步 Web 下載,然後按照呼叫順序等候。 請注意,當您執行程式時,工作不一定會依照建立及等待的順序完成。 它們在建立時開始執行,且一或多項工作可能會在方法到達 await 運算式之前結束。

注意事項注意事項

若要完成這個專案,您必須將 Visual Studio 2012、Visual Studio 2013、Visual Studio Express 2012 for Windows Desktop、Visual Studio Express 2013 for Windows 或 .NET Framework 4.5 或 4.5.1 安裝在您的電腦上。

如需同時啟動多個工作的其他範例,請參閱 如何:使用 Task.WhenAll 擴充非同步逐步解說的內容 (C# 和 Visual Basic)

您可以從開發人員程式碼範例下載此範例的程式碼。

若要設定專案

  • 若要建置 WPF 應用程式,請完成下列步驟。 您可以在 逐步解說:使用 Async 和 Await 存取 Web (C# 和 Visual Basic) 中找到這些步驟的詳細說明。

    • 建立包含文字方塊和按鈕的 WPF 應用程式。 將按鈕命名為 startButton,並將文字方塊命名為 resultsTextBox。

    • 加入 System.Net.Http 的參考。

    • 在 MainWindow.xaml.vb 或 MainWindow.xaml.cs 中,加入 Imports 陳述式或 System.Net.Http 的 using 指示詞。

加入程式碼

  1. 在 [設計] 視窗 MainWindow.xaml 中,按兩下按鈕建立 MainWindow.xaml.vb 或 MainWindow.xaml.cs 中的 startButton_Click 事件處理常式。 或者,選取按鈕,選取 [內容] 視窗的 [所選取項目的事件處理常式] 圖示,然後在 [按一下] 文字方塊中輸入 startButton_Click。

  2. 複製下列程式碼,並在 MainWindow.xaml.vb 或 MainWindow.xaml.cs 中,將它貼上至 startButton_Click 的主體。

    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";
    

    程式碼呼叫非同步方法 CreateMultipleTasksAsync,它會驅動這個應用程式。

  3. 將下列支援方法加入至專案:

    • ProcessURLAsync 使用 HttpClient 方法將網站的內容下載為位元組陣列。 支援方法, ProcessURLAsync 隨後顯示並傳回陣列的長度。

    • DisplayResults 顯示每個 URL 位元組陣列中的位元組數目。 每次完成下載工作時,會顯示這個畫面。

    複製下列方法,並在 MainWindow.xaml.vb 或 MainWindow.xaml.cs 中 startButton_Click 的事件處理常式之後貼上它們。

    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. 最後,定義方法 CreateMultipleTasksAsync,此方法會執行下列步驟。

    • 此方法會宣告 HttpClient 物件,針對此物件,您必須在 ProcessURLAsync中存取方法 GetByteArrayAsync

    • 此方法會建立並啟動 Task類型的工作,其中 TResult 是整數。 當每項工作完成時,DisplayResults 會顯示工作的 URL 和下載內容的長度。 由於工作是以非同步方式執行,結果出現的順序可能與其宣告的順序不同。

    • 此方法會等候每個工作完成。 每個 Await 或 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/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. 選取 F5 鍵執行程式,然後選擇 [開始] 按鈕。

    執行程式數次,確認這三項工作不一定會依照相同順序完成,而且完成的順序不一定是建立及等待的順序。

範例

下列程式碼包含完整的範例。

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

請參閱

工作

逐步解說:使用 Async 和 Await 存取 Web (C# 和 Visual Basic)

如何:使用 Task.WhenAll 擴充非同步逐步解說的內容 (C# 和 Visual Basic)

概念

使用 Async 和 Await 設計非同步程式 (C# 和 Visual Basic)