Ambas as respostas não mencionaram o esperado Task.WhenAll
:
var task1 = DoWorkAsync();
var task2 = DoMoreWorkAsync();
await Task.WhenAll(task1, task2);
A principal diferença entre Task.WaitAll
e Task.WhenAll
é que o primeiro será bloqueado (semelhante ao uso Wait
em uma única tarefa), enquanto o último não será e poderá ser aguardado, retornando o controle ao chamador até que todas as tarefas sejam concluídas.
Além disso, o tratamento de exceções é diferente:
Task.WaitAll
:
Pelo menos uma das instâncias da tarefa foi cancelada - ou - uma exceção foi lançada durante a execução de pelo menos uma das instâncias da tarefa. Se uma tarefa foi cancelada, o AggregateException contém um OperationCanceledException em sua coleção InnerExceptions.
Task.WhenAll
:
Se alguma das tarefas fornecidas for concluída em um estado com falha, a tarefa retornada também será concluída em um estado com falha, em que suas exceções conterão a agregação do conjunto de exceções não desempacotadas de cada uma das tarefas fornecidas.
Se nenhuma das tarefas fornecidas falhar, mas pelo menos uma delas foi cancelada, a tarefa retornada terminará no estado Cancelado.
Se nenhuma das tarefas falhar e nenhuma delas foi cancelada, a tarefa resultante terminará no estado RanToCompletion. Se a matriz / enumerável fornecida não contiver tarefas, a tarefa retornada passará imediatamente para um estado RanToCompletion antes de retornar ao chamador.
await Task.WhenAll(task1, task2);
?Task.WhenAll
não inicia as tarefas para você. Você precisa fornecê-los "quente", ou seja, já iniciado.StartNew
e girar novas tarefas têm a ver com a espera assíncrona de todas elas?Você pode criar muitas tarefas como:
fonte
A melhor opção que eu vi é o seguinte método de extensão:
Chame assim:
Ou com um lambda assíncrono:
fonte
Você pode usar o
WhenAll
que retornará um tipo de retorno aguardávelTask
ouWaitAll
que não tem retorno e bloqueará a execução de código adicional semelhanteThread.Sleep
até que todas as tarefas sejam concluídas, canceladas ou com falha.Exemplo
Se você deseja executar as tarefas em uma ordem prática, pode se inspirar nesta resposta.
fonte
await
para cada operação e ao mesmo tempo usaWaitAll
ouWhenAll
. As tarefas naTask[]
inicialização não deveriam ficar semawait
?Deseja encadear os
Task
s ou eles podem ser chamados de maneira paralela?Para encadear
Basta fazer algo como
e não se esqueça de verificar a
Task
instância anterior em cada uma,ContinueWith
pois ela pode estar com defeito.Pela maneira paralela
O método mais simples que me deparei:
Parallel.Invoke
Caso contrário, existeTask.WaitAll
ou você pode usarWaitHandle
s para fazer uma contagem regressiva para zero ações restantes (espere, há uma nova classeCountdownEvent
:) ou ...fonte
É assim que eu faço isso com uma matriz Func <> :
fonte
Mais uma resposta ... mas geralmente me encontro em um caso, quando preciso carregar dados simultaneamente e colocá-los em variáveis, como:
fonte
LoadCatsAsync()
eLoadDogAsync()
são apenas chamadas de banco de dados, elas são vinculadas a IO.Task.Run()
é para trabalho ligado à CPU; ele adiciona uma sobrecarga desnecessária adicional se tudo o que você está fazendo é aguardar uma resposta do servidor de banco de dados. A resposta aceita por Yuval é o caminho certo para o trabalho vinculado à IO.Eu preparei um pedaço de código para mostrar como usar a tarefa para alguns desses cenários.
fonte