Resumo : neste tutorial, você aprenderá como usar o WhenAll()
método estático C# da classe Task para criar uma tarefa que será concluída quando todas as tarefas de entrada forem concluídas.
Introdução ao método estático C# WhenAll()
O
método cria uma tarefa que será concluída assim que todas as tarefas de entrada forem concluídas. O método retorna um Task.WhenAll
()Task
objeto que representa a conclusão de todas as tarefas de entrada. A tarefa retornada contém os resultados de todas as tarefas de entrada.
Na prática,
é útil para agregar resultados de múltiplas operações assíncronas.Task.WhenAll
()
O programa a seguir demonstra o
método:Task.WhenAll
()
static async Task<int> DoWork(int taskId)
{
Console.WriteLine($"Task {taskId} started...");
await Task.Delay(TimeSpan.FromSeconds(taskId));
Console.WriteLine($"Task {taskId} finished.");
return taskId * taskId;
}
var t1 = Task.Run(() => DoWork(1));
var t2 = Task.Run(() => DoWork(2));
var t3 = Task.Run(() => DoWork(3));
int[] results = await Task.WhenAll(t1, t2, t3);
Console.WriteLine("Results:");
Console.WriteLine(string.Join(", ", results));
Linguagem de código: C# ( cs )
Saída:
ask 3 started...
Task 2 started...
Task 1 started...
Task 1 finished.
Task 2 finished.
Task 3 finished.
Results:
1, 4, 9
Linguagem de código: C# ( cs )
Como funciona.
Primeiro, defina um método chamado DoWork()
que aceite um parâmetro inteiro
. O método exibe uma mensagem indicando que a tarefa foi iniciada e atrasa um número especificado de segundos usando o taskId
método, e exibe outra mensagem mostrando que a tarefa foi concluída e retorna o quadrado de Task.Delay
()
:taskId
static async Task<int> DoWork(int taskId)
{
Console.WriteLine($"Task {taskId} started...");
await Task.Delay(TimeSpan.FromSeconds(taskId));
Console.WriteLine($"Task {taskId} finished.");
return taskId * taskId;
}
Linguagem de código: C# ( cs )
Como o método possui uma operação assíncrona, ele é marcado como um método assíncrono. Portanto, ele retorna um Task<int>
objeto em vez de um número inteiro.
Segundo, crie três tarefas usando o
método que executa o Task.Run
()DoWork()
método em threads em segundo plano:
var t1 = Task.Run(() => DoWork(1));
var t2 = Task.Run(() => DoWork(2));
var t3 = Task.Run(() => DoWork(3));
Linguagem de código: C# ( cs )
Terceiro, use o
método para aguardar a conclusão de três tarefas. O método retorna uma matriz de inteiros armazenados na variável de resultados:Task.WhenAll
()
int[] results = await Task.WhenAll(t1, t2, t3);
Linguagem de código: C# ( cs )
Por fim, mostre os resultados no console:
Console.WriteLine("Results:");
Console.WriteLine(string.Join(", ", results));
Linguagem de código: C# ( cs )
Aguardando a conclusão de várias solicitações HTTP usando o método Task.WhenAll()
O exemplo a seguir mostra como usar
e Task.WhenAll
()HttpClient
para buscar conteúdo de forma assíncrona de vários URLs
e calcular o total de bytes:
static async Task<int> Fetch(string url)
{
Console.WriteLine($"Fetching {url}...");
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Fetched {url} ({content.Length} bytes)");
return content.Length;
}
var t1 = Task.Run(() => Fetch("https://www.rfc-editor.org/rfc/rfc2616"));
var t2 = Task.Run(() => Fetch("https://www.rfc-editor.org/rfc/rfc2822"));
var t3 = Task.Run(() => Fetch("https://www.rfc-editor.org/rfc/rfc1180"));
var results = await Task.WhenAll(new[] { t1, t2, t3 });
Console.WriteLine($"Total {results.Sum()} bytes");
Linguagem de código: C# ( cs )
Saída:
Fetching https://www.rfc-editor.org/rfc/rfc2822...
Fetching https://www.rfc-editor.org/rfc/rfc1180...
Fetching https://www.rfc-editor.org/rfc/rfc2616...
Fetched https://www.rfc-editor.org/rfc/rfc2822 (141338 bytes)
Fetched https://www.rfc-editor.org/rfc/rfc1180 (80606 bytes)
Fetched https://www.rfc-editor.org/rfc/rfc2616 (521792 bytes)
Total 743736 bytes
Linguagem de código: C# ( cs )
Como funciona.
Primeiro, defina o Fetch()
método que recebe um argumento de string url
e retorna um Task<int>
objeto:
static async Task<int> Fetch(string url)
{
Console.WriteLine($"Fetching {url}...");
var httpClient = new HttpClient();
var response = await httpClient.GetAsync(url);
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Fetched {url} ({content.Length} bytes)");
return content.Length;
}
Linguagem de código: C# ( cs )
O Fetch()
método usa o HttpClient
objeto para buscar o conteúdo da entrada url
de forma assíncrona. Depois de concluir o download do conteúdo da URL, ele obtém o tamanho do conteúdo em bytes. e retorne-o como o valor inteiro envolvido em um Task
objeto.
Em segundo lugar, crie três tarefas usando o Task.Run
método para executar o Fetch()
método de forma assíncrona:
var t1 = Task.Run(() => Fetch("https://www.rfc-editor.org/rfc/rfc2616"));
var t2 = Task.Run(() => Fetch("https://www.rfc-editor.org/rfc/rfc2822"));
var t3 = Task.Run(() => Fetch("https://www.rfc-editor.org/rfc/rfc1180"));
Linguagem de código: C# ( cs )
Terceiro, espere que todas as três tarefas sejam concluídas usando o
método e retorne uma matriz de seus resultados como Task.WhenAll
()Task<int[]>
objeto:
var results = await Task.WhenAll(new[] { t1, t2, t3 });
Linguagem de código: C# ( cs )
Por fim, calcule o tamanho total do conteúdo buscado somando o tamanho do conteúdo de cada tarefa usando o Sum()
método de extensão e exiba o resultado:
Console.WriteLine($"Total {results.Sum()} bytes");
Linguagem de código: C# ( cs )
Resumo
- Use o
método para criar uma tarefa que será concluída assim que todas as tarefas de entrada forem concluídas.Task.WhenAll
()