等待IEnumerable项目(等待之后等待)

M.k*_*ary 3 .net c# linq asynchronous async-await

我有这个iterator- return类型,IEnumerable<Task<Event>>以便以后可以等待每个项目:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我想将其传递给构造函数。

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));
}
Run Code Online (Sandbox Code Playgroud)

构造函数采用此参数。

internal EventManager([NotNull, NoEnumeration]IEnumerable<Event> events) {...}
Run Code Online (Sandbox Code Playgroud)

这段代码会异步运行吗?

因为即使方法被标记为异步,我也无法在lambda中等待。我试图做一些修改。

我了解为什么Select(async e => await e)返回,IEnumerable<Task<Event>>因为async e => await e是异步方法,该返回类型必须包装在里面Task

我的问题是.Select(x => x.Result)仍会异步运行吗?因为我在此之前正在等待物品,所以这应该不是问题吧?就像写这个

await e;
return e.Result; // is it safe?
Run Code Online (Sandbox Code Playgroud)

我不想使用Task.WhenAll,因为这将枚举所有内容,而这正是我要避免的事情。我想保持此迭代器不变,直到其传入构造函数。我想推迟执行。(如果无法实现,我将使用工厂方法)

Ste*_*ary 5

这段代码会异步运行吗?

否。枚举枚举时,它将同步运行,并有可能出现死锁

Select(async e => await e)什么也没做 与相同Select(e => e)。它是一样的await e;

整个流到的转换IEnumerable<T>非常奇怪。也许您打算将其转换为IObservable<T>

如果这种方法不可行,我将使用工厂方法

是的,您不能await在构造函数中使用,阻塞会导致死锁。异步工厂方法可能是您最好的选择。