Escribir de forma asíncrona a un IAsyncEnumerable.
Estoy utilizando IAsyncEnumerable para devolver resultados paginados de una API a medida que llegan, de la siguiente manera:
public async IAsyncEnumerable
int startIndex = 0;
PaginatedResponse
do {
response = await _client.GetResults(_endpoint, startIndex, _pageSize);
foreach (var obj in response.Items){
yield return obj;
}
startIndex = response.StartIndex + response.Count;
} while (response.StartIndex + response.Count < response.Total);
}
Lo que quiero es enviar solicitudes para varias páginas en paralelo y devolver cada página a IAsyncEnumerable a medida que llega. El orden no importa.
¿Es posible lo que intento hacer? ¿Puedo tener varias tareas asíncronas escribiendo en el mismo IAsyncEnumerable que mi método devuelve? Lo mejor que se me ocurre es tener las tareas escribir en un IList común, y luego, después de que todas las tareas estén completas, iterar sobre ese IList y devolver todos los elementos:
public async Task<IAsyncEnumerable
int totalPages = _client.MagicGetTotalPagesMethod();
IList
var tasks = Enumerable.Range(0,totalPages).Select(async x => {
// mi objetivo es devolver desde aquí, en lugar de agregarlo al IList y devolverlo después de que se completen todas las tareas
results.AddRange(await _client.GetResults(_endpoint, x*_pageSize, _pageSize));
});
await Task.WhenAll(tasks);
foreach (var result in results){
yield return result;
}
}
Esto resuelve parcialmente el problema al tener varias solicitudes activas al mismo tiempo, pero todavía tenemos que esperar a que todas regresen antes de que el consumidor de GetResults pueda usar los resultados.
davy.ai
¿Existe una mejor manera de hacer esto?
Sí, es posible tener múltiples tareas asíncronas escribiendo en el mismo
IAsyncEnumerable
que devuelve su método.Puede usar el método
Concat
para combinar múltiplesIAsyncEnumerable
en uno y luego usarSelectMany
para aplanar los resultados en un soloIAsyncEnumerable
. Esto le permitirá realizar múltiples solicitudes en paralelo y devolver los resultados a medida que lleguen.Por ejemplo: