C# quando tudo

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 Task.WhenAll()método cria uma tarefa que será concluída assim que todas as tarefas de entrada forem concluídas. O método retorna um Taskobjeto 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, Task.WhenAll()é útil para agregar resultados de múltiplas operações assíncronas.

O programa a seguir demonstra o Task.WhenAll()método:

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, 9Linguagem de código:  C#  ( cs )

Como funciona.

Primeiro, defina um método chamado DoWork()que aceite um parâmetro inteiro taskId. O método exibe uma mensagem indicando que a tarefa foi iniciada e atrasa um número especificado de segundos usando o Task.Delay()método, e exibe outra mensagem mostrando que a tarefa foi concluída e retorna o quadrado de 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 Task.Run()método que executa o 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 Task.WhenAll()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:

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 Task.WhenAll()e HttpClientpara buscar conteúdo de forma assíncrona de vários URLse 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 bytesLinguagem de código:  C#  ( cs )

Como funciona.

Primeiro, defina o Fetch()método que recebe um argumento de string urle 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 HttpClientobjeto para buscar o conteúdo da entrada urlde 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 Taskobjeto.

Em segundo lugar, crie três tarefas usando o Task.Runmé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 Task.WhenAll()método e retorne uma matriz de seus resultados como 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 Task.WhenAll()método para criar uma tarefa que será concluída assim que todas as tarefas de entrada forem concluídas.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *