Gostaria de lidar com uma coleção em paralelo, mas estou tendo problemas para implementá-la e, portanto, espero por alguma ajuda.
O problema surge se eu quiser chamar um método marcado como assíncrono em C #, dentro do lambda do loop paralelo. Por exemplo:
var bag = new ConcurrentBag<object>();
Parallel.ForEach(myCollection, async item =>
{
// some pre stuff
var response = await GetData(item);
bag.Add(response);
// some post stuff
}
var count = bag.Count;
O problema ocorre com a contagem sendo 0, porque todos os threads criados são efetivamente apenas threads de segundo plano e a Parallel.ForEach
chamada não espera pela conclusão. Se eu remover a palavra-chave assíncrona, o método será assim:
var bag = new ConcurrentBag<object>();
Parallel.ForEach(myCollection, item =>
{
// some pre stuff
var responseTask = await GetData(item);
responseTask.Wait();
var response = responseTask.Result;
bag.Add(response);
// some post stuff
}
var count = bag.Count;
Funciona, mas desativa completamente a esperteza esperada e eu tenho que fazer um tratamento manual de exceções .. (Removido por questões de brevidade).
Como posso implementar um Parallel.ForEach
loop, que usa a palavra-chave wait dentro do lambda? É possível?
O protótipo do método Parallel.ForEach usa um Action<T>
parâmetro as, mas quero que ele aguarde minha lambda assíncrona.
await
doawait GetData(item)
seu segundo bloco de código, pois isso produziria um erro de compilação como está.Respostas:
Se você apenas deseja um paralelismo simples, pode fazer o seguinte:
Se você precisar de algo mais complexo, confira o
ForEachAsync
post de Stephen Toub .fonte
dop
tarefas e cada uma delas processa algum subconjunto da coleção de entradas em série.Task.Run
sem obterawait
o resultado, isso é apenas um trabalho de disparar e esquecer no pool de threads. Isso quase sempre é um erro.Você pode usar o
ParallelForEachAsync
método de extensão do pacote NuGet do AsyncEnumerator :fonte
maxDegreeOfParallelism
>maxDegreeOfParalellism
Com
SemaphoreSlim
você pode conseguir o controle do paralelismo.fonte
Minha implementação leve do ParallelForEach assíncrono.
Recursos:
Exemplo de uso:
fonte
Eu criei um método de extensão para isso, que usa o SemaphoreSlim e também permite definir o grau máximo de paralelismo
Uso da amostra:
fonte