É possível usar Async ao usar ForEach? Abaixo está o código que estou tentando:
using (DataContext db = new DataLayer.DataContext())
{
db.Groups.ToList().ForEach(i => async {
await GetAdminsFromGroup(i.Gid);
});
}
Estou recebendo o erro:
O nome 'Async' não existe no contexto atual
O método em que a instrução using está incluída é definido como assíncrono.
c#
async-await
James Jeffery
fonte
fonte
List.ForEach()
não faz parte do LINQ.async
. Eles têm sido muito úteis!foreach
com umawait
em seu corpo de loop.ForEach
aceita apenas um tipo de delegado síncrono e não há sobrecarga em um tipo de delegado assíncrono. Portanto, a resposta curta é "ninguém escreveu um assíncronoForEach
". A resposta mais longa é que você teria que assumir alguma semântica; por exemplo, os itens devem ser processados um de cada vez (comoforeach
) ou simultaneamente (comoSelect
)? Se um de cada vez, os fluxos assíncronos não seriam uma solução melhor? Se simultaneamente, os resultados devem estar na ordem do item original ou na ordem de conclusão? Deve falhar na primeira falha ou esperar até que tudo seja concluído? Etc.SemaphoreSlim
para controlar tarefas assíncronas.Este pequeno método de extensão deve fornecer iteração assíncrona segura com exceção:
Como estamos alterando o tipo de retorno do lambda de
void
paraTask
, as exceções serão propagadas corretamente. Isso permitirá que você escreva algo assim na prática:fonte
async
deveria ser antesi =>
ForEachAsync
é essencialmente um método de biblioteca, portanto, o awaiting provavelmente deve ser configurado comConfigureAwait(false)
.A resposta simples é usar a
foreach
palavra - chave em vez doForEach()
método deList()
.fonte
Aqui está uma versão funcional real das variantes de foreach assíncronas acima com processamento sequencial:
Aqui está a implementação:
Qual é a principal diferença?
.ConfigureAwait(false);
que mantém o contexto do thread principal durante o processamento sequencial assíncrono de cada tarefa.fonte
Começando com
C# 8.0
, você pode criar e consumir fluxos de forma assíncrona.Mais
fonte
MoveNext
do enumerador. Isso é importante nos casos em que o enumerador não pode buscar o próximo elemento instantaneamente e deve esperar que um fique disponível.Adicionar este método de extensão
E então use assim:
fonte
O problema era que a
async
palavra - chave precisava aparecer antes do lambda, não antes do corpo:fonte
async void
. Essa abordagem tem problemas em torno do tratamento de exceções e de saber quando as operações assíncronas são concluídas.