Let's say I have a sequence of integers I obtain asynchronously.
async Task<int> GetI(int i){
return await Task.Delay(1000).ContinueWith(x => i);
}
I want to create a generator over that sequence, if the sequence was synchronous I'd do:
IEnumerable<int> Method()
{
for (var i = 0; i < 100; i++)
{
yield return GetI(i); // won't work, since getI returns a task
}
}
So, I figured the analogy is making the generator async and yielding from it:
async Task<IEnumerable<int>> Method()
{
for (var i = 0; i < 100; i++)
{
yield return await Task.Delay(1000).ContinueWith(x => i);
}
}
This won't work, since a method with yield
must return an IEnumerable
of something, the alternative, which makes more sense is IEnumerable<Task<int>>
but that won't compile since async
methods must return Task
s or void.
Now, I realize I can simply remove the await and return an IEnumerable<Task<int>>
but that won't help me since the iteration will keep asking for data before any of it is ready, so it doesn't solve my issue.
- Is there any way to nicely mix enumerables and tasks with the nice sugar the language gives me with await and yield?
- Is there any way to nicely consume it?
(From searching online, I suspect the answer to the first question is false and the second one is an observer/observable, but I couldn't find any canonical reference and I'm interested in the best way to implement this pattern in C#)
Task<IEnumerable<int>>
, or anIEnumerable<Task<int>>
? The latter is significantly easier to achieve... but it's not clear what you're actually trying to get out of this. – HowlandTask<IEnumerable<Task<int>>>
, I want to get an iterator that I'll wait for initially and then wait for at each iteration. However, anIEnumerable<Task<int>>
is also acceptable, the problem is as I mention in the question is that the IEnumerable will get consumed synchronously on the consumer where I want to wait for it at every iteration before consuming the next element. I'm wondering if there is a clever way to do this that does not involve a regular for loop pausing the iteration byawait
there. – IsoclinalIAsyncEnumerable
which exposes per-element asynchrony. – Suborn