You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从任务枚举集合创建IAsyncEnumerable?

解决方案

你遇到的核心问题是:Select(async e => ...)会立即遍历整个watchlist并启动所有异步任务,所以所有GetMovieFromWatchlistEntry的调用会同时执行,和后续的Task.WhenAll无关。想要实现「逐个创建并等待任务」的延迟求值,不能从已有的moviePromises集合转换(因为任务已经启动了),需要直接用IAsyncEnumerable从源头控制任务的执行时机。

正确实现方式

直接编写异步迭代器方法,在迭代时才逐个启动并等待任务:

// 定义异步迭代器方法,返回IAsyncEnumerable<Movie>
public async IAsyncEnumerable<Movie> GetMoviesFromWatchlistAsync()
{
    foreach (var entry in this.watchlist)
    {
        // 每次迭代时才调用并等待当前任务完成
        var movie = await this.GetMovieFromWatchlistEntry(entry);
        yield return movie;
    }
}

然后用await foreach遍历执行:

await foreach (var movie in GetMoviesFromWatchlistAsync())
{
    // do stuff
}

为什么原来的方式不行?

Select(async e => await this.GetMovieFromWatchlistEntry(e))会立即枚举整个watchlist,对每个元素执行lambda表达式——而async lambda会立即启动异步任务并返回Task<Movie>,所以所有任务在Select执行时就已经同时跑起来了,后续的Task.WhenAll只是等待它们全部完成而已,无法控制逐个执行。

关于从现有moviePromises转换的说明

如果硬要从已有的IEnumerable<Task<Movie>>转换为IAsyncEnumerable,可以写如下方法:

public async IAsyncEnumerable<Movie> TasksToAsyncEnumerable(IEnumerable<Task<Movie>> tasks)
{
    foreach (var task in tasks)
    {
        yield return await task;
    }
}

但这种方式无法改变任务已经同时启动的事实,达不到你想要的延迟求值、逐个执行的效果,因此不推荐。

内容的提问来源于stack exchange,提问作者codymanix

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 10:20:00