49

一度に 1 つずつではなく、一度に複数のアイテムを ConcurrentBag に追加する方法はありますか? ConcurrentBag には AddRange() メソッドはありませんが、Concat() はあります。しかし、それは私にとってはうまくいきません:

ConcurrentBag<T> objectList = new ConcurrentBag<T>();

timeChunks.ForEach(timeChunk =>
{
    List<T> newList = Foo.SomeMethod<T>(x => x.SomeReadTime > timeChunk.StartTime);
    objectList.Concat<T>(newList);
});

このコードは以前 Parallel.ForEach() に含まれていましたが、トラブルシューティングできるように上記のように変更しました。変数 newList には確かにオブジェクトがありますが、objectList.Concat<> 行の後では、objectList には常に 0 オブジェクトが含まれています。Concat<> はそのように機能しませんか? Add() メソッドを使用して、アイテムを一度に 1 つずつ ConcurrentBag に追加する必要がありますか?

4

6 に答える 6

73

(これは古い投稿であることを知っています。少し何かを追加すると思いました)。

他の人が言ったように: はい、それらを 1 つずつ追加する必要があります。私の場合、物事を少しきれいにするために小さな拡張メソッドを追加しましたが、ボンネットの下では同じことを行います。

    public static void AddRange<T>(this ConcurrentBag<T> @this, IEnumerable<T> toAdd)
    {
        foreach (var element in toAdd)
        {
            @this.Add(element);
        }
    }

その後:

    ConcurrentBag<int> ccBag = new ConcurrentBag<int>();
    var listOfThings = new List<int>() { 1, 2, 4, 5, 6, 7, 8, 9 };
    ccBag.AddRange(listOfThings);

AsParallel を使用して拡張メソッド内に追加することも検討しましたが、さまざまなサイズの文字列のリストを追加するいくつかのテストを実行した後、従来の for ループとは対照的に、AsParallel (ここに示すように) を使用する方が一貫して遅くなりました。

    public static void AddRange<T>(this ConcurrentBag<T> @this, IEnumerable<T> toAdd)
    {
        toAdd.AsParallel().ForAll(t => @this.Add(t));
    }
于 2015-06-30T17:38:04.550 に答える
20

ConcatLINQ が提供する拡張メソッドです。IEnumerableこれは、ソース コレクションの直後に指定されたコレクションを列挙できる別の操作を返す、不変の操作です。ソース コレクションが変更されることはありません。

アイテムを 1 つずつ追加する必要がありますConcurrentBag

于 2012-04-16T16:18:48.160 に答える
9

送信側のデータにアクセスするために使用していた Web サービスが 1 つの大きなチャンクでタイムアウトしていたため、データの小さなチャンクを並行して処理しようとして、同様の問題に直面しましたが、各チャンクを処理することで動作が遅くなりたくなかったためです。連続して。レコードごとのデータ処理はさらに遅くなりました。私が呼び出していたサービスは大量のリクエストを処理できるため、タイムアウトせずにできるだけ多くのリクエストを送信したほうがよいでしょう。

Vlad が言ったように、並行バッグをオブジェクト型のリストに連結しても並行バッグは返されないため、連結は機能しません! (それができないことに気付くのに少し時間がかかりました。)

代わりにこれを試してください - を作成しList<T>、次に を作成しConcurrentBag<List<T>>ます。並列反復ごとに、新しいリストが同時実行バッグに追加されます。並列ループが完了したら、すべてを 1 つのリストに「平坦化」するためConcurrentBagに最初に作成したものまで and concat (重複の可能性を排除したい場合は結合) をループします。List<T>

于 2015-05-21T14:09:50.273 に答える
-5

はい :)

ConcatおそらくEnumerable拡張機能の1つです。には何も追加しませんConcurrentBag。元のバッグとそこに追加しようとしたものを含むファンキーなオブジェクトを返すだけです。

の結果はもはや でConcatはないConcurrentBagので、使用したくないことに注意してください。これは一般的な LINQ フレームワークの一部であり、不変のシーケンスを組み合わせることができます。もちろん、このフレームワークは、オペランドの並行プロパティを結果に拡張しようとしないため、結果のオブジェクトはマルチスレッド アクセスにはあまり適していません。

(基本的には、インターフェースを公開しているためにConcat適用されます。)ConcurrentBagIEnumerable<T>

于 2012-04-16T16:16:03.953 に答える