Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Await for IEnumerable items, (wait after await)

I have this iterator- return type is IEnumerable<Task<Event>> so that I can await for each item later:

private IEnumerable<Task<Event>> GetEventsAsync(long length)
{
    var pos = _reader.BaseStream.Position;
    while (_reader.BaseStream.Position - pos < length)
    {
        yield return ReadEvent(); // this method is async
    }
}

Now I want to pass this in to constructor.

private async Task<EventManager> ReadEventManagerAsync()
{
    // some other stuff
    var length = Reverse(await _reader.ReadInt32()); // bytes to read
    var events = GetEventsAsync(length); // cant await iterator. so use linq
    return new EventManager(events.Select(async e => await e).Select(x => x.Result));
}

The constructor takes this parameter.

internal EventManager([NotNull, NoEnumeration]IEnumerable<Event> events) {...}

Will this code run asynchronously?

Because I cant await inside lambda even if method is marked as async. I tried to do some hack.

I Understand why Select(async e => await e) returns IEnumerable<Task<Event>> because async e => await e is async method, which return type must be wrapped inside Task

My question is will .Select(x => x.Result) still run async? because I'm awaiting items before this so this shouldn't be a problem right? its like writing this

await e;
return e.Result; // is it safe?

I don't want to use Task.WhenAll because that will enumerate all stuff and that's the thing I'm trying to avoid. I want to keep this iterator untouched until its passed in constructor. I want to keep the execution deferred. (I will use factory method if this approach is not possible)

like image 887
M.kazem Akhgary Avatar asked Dec 19 '25 06:12

M.kazem Akhgary


1 Answers

Will this code run asynchronously?

No. When the enumerable is enumerated, it will run synchronously, complete with possibility of deadlocks.

Select(async e => await e) doesn't do anything. It's the same as Select(e => e). It is not the same as await e;.

The whole converting-stream-to-IEnumerable<T> is extremely odd. Perhaps you meant to convert it to IObservable<T>?

I will use factory method if this approach is not possible

Yes, you cannot use await in a constructor, and blocking can cause deadlocks. An asynchronous factory method is probably your best bet.

like image 62
Stephen Cleary Avatar answered Dec 21 '25 20:12

Stephen Cleary



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!