Postupy: Paralelní provádění vícenásobných webových dotazů pomocí modifikátoru Async a operátoru Await (C# and Visual Basic)
V asynchronní metodě jsou úlohy spuštěny při vytvoření.Operátor Await (Visual Basic) nebo await (C#) se použije na úlohu v okamžiku v metodě, kdy zpracování nemůže pokračovat, dokud neskončí úloha.Úloha je často očekávaná ihned, jakmile je vytvořena, jak ukazuje následující příklad.
Dim result = Await someWebAccessMethodAsync(url)
var result = await someWebAccessMethodAsync(url);
Pokud má však program provádět jinou práci, která nezávisí na dokončení úkolu, můžete oddělit vytvoření úkolu od čekání na úkol.
' 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;
Mezi spuštěním úlohy a čekáním na ni můžete spustit další úkoly.Další úkoly jsou implicitně spuštěny paralelně, ale žádné další vlákna nejsou vytvořena.
Následující program spustí tři asynchronní webové soubory ke stažení a pak je čeká v pořadí, ve kterém jsou volány.Všimněte si, že při spuštění programu nejsou úlohy vždy dokončeny v pořadí, ve kterém byly vytvořeny a očekávány.Spustí se po vytvoření a jeden nebo více úkolů může skončit dříve, než metoda dosáhne výrazů await.
[!POZNÁMKA]
Chcete-li dokončit tento projekt, musíte mít nainstalovanou aplikaci Visual Studio 2012, Visual Studio 2013, Visual Studio Express 2012 for Windows Desktop, Visual Studio Express 2013 for Windows nebo rozhraní .NET Framework 4.5 nebo 4.5.1 v počítači.
Další příklad spuštění více úloh současně naleznete zde: Postupy: Rozšíření návodu asynchronních úloh pomocí metody Task.WhenAll (C# and Visual Basic).
Můžete si kód pro tento příklad z tématu Ukázky kódu vývojáře.
Vytvoření projektu
Chcete-li nastavit aplikaci WPF, proveďte následující kroky.Podrobné pokyny k těmto krokům uvádí téma Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic).
Vytvořte aplikaci WPF, která obsahuje textové pole a tlačítko.Pojmenujte tlačítko startButton a pojmenujte textového pole resultsTextBox.
Přidejte odkaz pro System.Net.Http.
Do souborů MainWindow.xaml.vb nebo MainWindow.xaml.cs přidejte příkaz Imports nebo direktivu using pro System.Net.Http.
Přidání kódu
V okně návrhu, MainWindow.xaml, kliknutím dvakrát na tlačítko vytvořte obslužnou rutinu události startButton_Click v souboru MainWindow.xaml.vb nebo MainWindow.xaml.cs.Alternativně klepněte na tlačítko, vyberte ikonu Obslužné rutiny událostí pro vybrané prvky v okně Vlastnosti a potom zadejte startButton_Click v textovém poli Klikněte.
Následující kód zkopírujte a vložte jej do hlavní části startButton_Click pro MainWindow.xaml.vb nebo 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";
Kód volá metodu asynchronní metodu CreateMultipleTasksAsync, která řídí aplikaci.
Do projektu přidejte následující metody podpory:
ProcessURLAsync používá metodu HttpClient ke stažení obsahu webu jako bajtové pole.Podpůrná metoda ProcessURLAsync potom zobrazí a vrátí délku pole.
DisplayResults zobrazí počet bajtů pro každou adresu URL v bajtovém poli.Toto zobrazení se ukazuje po dokončení stahování jednotlivých úkolů.
Následující metody zkopírujte a vložte je za obslužnou rutinu události startButton_Click pro MainWindow.xaml.vb nebo 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); }
Nakonec definujte metodu CreateMultipleTasksAsync, která provede následující kroky.
Metoda deklaruje objekt HttpClient, který potřebuje získat přístup k metodě GetByteArrayAsync v ProcessURLAsync.
Metoda vytvoří a spustí tři úkoly typu Task, kde TResult je celé číslo.Jak je každý úkol dokončen, DisplayResults zobrazí adresu URL úkolu a délku staženého obsahu.Vzhledem k tomu, že úkoly jsou spouštěny asynchronně, pořadí zobrazení výsledků se může lišit od pořadí, v němž byly deklarovány.
Metoda čeká na ukončení každého úkolu.Každý operátor Await nebo await pozastaví provádění CreateMultipleTasksAsync, dokud nebude dokončena očekávaná úloha.Operátor také použije vrácenou hodnotu z volání do ProcessURLAsync z každého dokončeného úkolu.
Když byly úlohy dokončeny a celočíselné hodnoty byly načteny, metoda sečte délky webových stránek a zobrazí výsledek.
Následující metodu zkopírujte a vložte do vašeho řešení.
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); }
Zvolte klávesu F5 ke spuštění programu a pak zvolte tlačítko Start.
Spusťte program několikrát, chcete-li ověřit, zda ve stejném pořadí nejsou vždy dokončeny tři úkoly a pořadí, ve kterém jsou dokončeny, není nutně pořadí, ve kterém byly vytvořeny nebo očekávány.
Příklad
Následující kód obsahuje úplný příklad.
' 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);
}
}
}
Viz také
Úkoly
Návod: Přístup k webu pomocí modifikátoru Async a operátoru Await (C# a Visual Basic)
Postupy: Rozšíření návodu asynchronních úloh pomocí metody Task.WhenAll (C# and Visual Basic)
Koncepty
Asynchronní programování pomocí modifikátoru Async a operátoru Await (C# a Visual Basic)