3

我正在尝试优化一个看起来像这样(简化)的例程:

public async Task<IEnumerable<Bar>> GetBars(ObjectId id){
    var output = new Collection<Bar>();

    var page = 1;
    var hasMore = true;

    while(hasMore) {
        var foos = await client.GetFoos(id, page);

        foreach(var foo : foos) {

            if(!Proceed(foo)) {
                hasMore = false;
                break;
            }

            output.Add(new Bar().Map(foo)
        }

        page++;

    return output;
}

调用的方法GetBars()看起来像这样

public async Task<Baz> GetBaz(ObjectId id){
    var bars = await qux.GetBars();

    if(bars.Any() {
        var bazBaseData = qux.GetBazBaseData(id);
        var bazAdditionalData = qux.GetBazAdditionalData(id);

        return new Baz().Map(await bazBaseData, await bazAdditionalData, bars);
    }
}

GetBaz()返回 0 到很多项目之间。由于我们运行了几百万个 id,我们最初添加了该if(bars.Any())语句作为加速应用程序的初步尝试。

由于GetBars()等待它阻塞线程,直到它收集了所有数据(这可能需要一些时间)。我的想法是使用 yield return ,然后if(bars.Any())用一个检查来测试我们是否得到至少一个元素,这样我们就可以同时触发另外两个异步方法(这也需要一些时间来执行)。

我的问题是如何做到这一点。我知道System.Linq.Count()System.Linq.Any()击败了收益回报的整个想法,如果我检查可枚举中的第一项,它将从可枚举中删除。

除了添加例如 out 参数之外,还有其他/更好的选择GetBars()吗?

TL;DR:如何检查来自收益返回的可枚举对象是否包含任何对象而不开始迭代它?

4

1 回答 1

4

对于您的实际问题“如何检查来自收益返回的可枚举对象是否包含任何对象而不开始迭代它?” 好吧,你没有。

就这么简单,你不能用 IEnumerable 做的唯一事情就是枚举它。但是,调用 Any() 不是问题,因为“确实”仅枚举第一个元素(而不是整个列表),但不可能枚举任何内容,因为除了 a 之外,许多可枚举不以任何形式存在管道(可能没有支持集合,无法检查不存在的东西是否有任何元素,按设计这是没有意义的)

编辑:另外,我在您的代码中看不到任何收益,您是否混淆了等待和收益概念(完全不相关)?

于 2014-11-10T12:17:00.437 回答