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()すべてのデータを収集するまでスレッドをブロックします (時間がかかる場合があります)。if(bars.Any())私のアイデアは、yield return を使用してから、少なくとも 1 つの要素を取得したかどうかをテストするチェックに置き換えて、その間に他の 2 つの非同期メソッドを起動できるようにすることでした (これも実行に時間がかかります)。

私の質問は、これを行う方法です。私は利回りリターンの全体的なアイデアを知っSystem.Linq.Count()System.Linq.Any()いて無効にし、列挙可能な最初の項目をチェックすると、列挙可能なものから削除されます。

たとえば、 out パラメータをに追加する以外に、別の/より良いオプションはありますGetBars()か?

TL;DR: 反復を開始せずに、yield リターンからの列挙型にオブジェクトが含まれているかどうかを確認するにはどうすればよいですか?

4

1 に答える 1

4

あなたの実際の質問については、「yield return からの列挙可能オブジェクトに、反復を開始せずにオブジェクトが含まれているかどうかを確認するにはどうすればよいですか?」まあ、あなたはしません。

それはとても簡単です.IEnumerableでできることは列挙することだけなので、期間を設定することはできません. Any() を呼び出すことは問題ではありませんが、それは最初の要素のみ (リスト全体ではなく) を列挙するだけなので、何も列挙することはできません。パイプライン (バッキング コレクションがない可能性があります。存在しないものがまだ要素を持っているかどうかを確認することはできません。設計上、これは意味がありません)

編集:また、コードにyieldが表示されません.awaitableとyieldの概念(まったく関係ありません)を混同していますか?

于 2014-11-10T12:17:00.437 に答える