I am using IAsyncEnumerable
to return paginated results from an API as they come in, as follows:
public async IAsyncEnumerable<ApiObject> GetResults(){
int startIndex = 0;
PaginatedResponse<ApiObject> response;
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);
}
What I want is to send requests for multiple pages in parallel, and return each page to the IAsyncEnumerable
as it comes in. Order does not matter.
Is what I'm attempting to do possible? Can I have multiple asynchronous Tasks writing to the same IAsyncEnumerable
that my method is returning? The best I can come up with is to have the tasks write to a common IList
, then after all tasks complete, iterate over that IList and return all elements:
public async Task<IAsyncEnumerable<ApiObject>> GetResults(){
int totalPages = _client.MagicGetTotalPagesMethod();
IList<ApiObject> results = new List<ApiObject>();
var tasks = Enumerable.Range(0,totalPages).Select(async x => {
// my goal is to somehow return from here, rather than aggregating into the IList and returning after all tasks are done
results.AddRange(await _client.GetResults(_endpoint, x*_pageSize, _pageSize));
});
await Task.WhenAll(tasks);
foreach (var result in results){
yield return result;
}
}
This partially solves the problem by having multiple requests out at once, but we still have to wait for all of them to return before the consumer of this GetResults
can use the results.