Me gustaría manejar una colección en paralelo, pero tengo problemas para implementarla y, por lo tanto, espero ayuda.
El problema surge si quiero llamar a un método marcado asíncrono en C #, dentro de la lambda del bucle paralelo. Por ejemplo:
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;
El problema ocurre cuando el recuento es 0, porque todos los subprocesos creados son efectivamente solo subprocesos en segundo plano y la Parallel.ForEach
llamada no espera su finalización. Si elimino la palabra clave asíncrona, el método se ve así:
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, pero deshabilita por completo la agudeza de espera y tengo que hacer un manejo manual de excepciones. (Eliminado por brevedad).
¿Cómo puedo implementar un Parallel.ForEach
bucle que usa la palabra clave wait dentro de lambda? ¿Es posible?
El prototipo del método Parallel.ForEach toma un Action<T>
parámetro como, pero quiero que espere mi lambda asíncrona.
await
deawait GetData(item)
en su segundo bloque de código, ya que produciría un error de compilación como está.Respuestas:
Si solo quieres un paralelismo simple, puedes hacer esto:
Si necesitas algo más complejo, mira la
ForEachAsync
publicación de Stephen Toub .fuente
dop
tareas y cada una de ellas procesa algún subconjunto de la colección de entrada en serie.Task.Run
sin obtenerawait
el resultado, entonces eso es solo lanzar trabajo de disparar y olvidar en el grupo de subprocesos. Eso casi siempre es un error.Puede usar el
ParallelForEachAsync
método de extensión del paquete AsyncEnumerator NuGet :fuente
maxDegreeOfParallelism
>maxDegreeOfParalellism
Con
SemaphoreSlim
usted puede lograr el control de paralelismo.fuente
Mi implementación ligera de ParallelForEach async.
caracteristicas:
Ejemplo de uso:
fuente
He creado un método de extensión para esto que hace uso de SemaphoreSlim y también permite establecer el grado máximo de paralelismo
Uso de muestra:
fuente