c# - Throttle asincroniza las tareas?
.net asynchronous (1)
Me gustaría saber si deberíamos acelerar las tareas asincrónicas si la cantidad de tareas para completar es grande. Digamos que tiene 1000 URL, dispara todas las solicitudes a la vez y espera por todas:
var tasks = urlList.Select(url => downloadAsync(url));
await Task.WhenAll(tasks);
¿O lote las solicitudes y procesa un lote tras otro?
foreach (var urlBatch in urlList.BatchEnumerable(BatchSize)){
var tasks = urlBatch.Select(url => downloadAsync(url));
await Task.WhenAll(tasks);
}
Pensé que el procesamiento por lotes no es necesario, ya que el primer enfoque (activar todas las solicitudes a la vez) creará tareas programadas por ThreadPool
, por lo que deberíamos dejar que ThreadPool
decida cuándo ejecutar cada tarea. Sin embargo, me dijeron que en la práctica solo funciona si las tareas son tareas de cálculo. Cuando las tareas involucran solicitudes de red, ¿el primer acercamiento podría causar que la máquina host cuelgue? Porqué es eso ?
Desea limitarse a algo en la mayoría de los casos. Siempre tiene algún estado guardado en algún lugar cuando tiene varias operaciones ejecutándose simultáneamente. Si están vinculados a la CPU, las tareas se almacenan en la cola ThreadPool
esperando un hilo y si es asíncrono, entonces tiene la máquina de estado en el montón.
Incluso las operaciones asincrónicas suelen usar algún recurso limitado, ya sea banda ancha, puertos, CPU del servidor de base de datos remota, etc.
Sin embargo, no tiene que limitarse a un único lote por vez (ya que debe esperar a que se complete la última operación en lugar de iniciar otras). Puede estrangular utilizando un SlimSemahpore
o incluso mejor, un bloque TPL Dataflow:
var block = new ActionBlock<string>(
url => downloadAsync(url),
new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 10 });
urlList.ForEach(url => block.Post(url));
block.Complete();
await block.Completion;