2012-04-16 15 views
21

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

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には常にオブジェクトがあります。 Concat <はそのようには機能しませんか? Add()メソッドを使用して、ConcurrentBagにアイ​​テムを1つずつ追加する必要がありますか?

答えて

5

はい:)

Concatは、おそらくEnumerable拡張子の一つです。 ConcurrentBagには何も追加されません。元のバッグを入れたものや、そこに追加しようとしたものを返します。

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

(それはIEnumerable<T>インターフェースを公開するので、基本的にConcatConcurrentBagに適用される。)

19

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

あなたは一度に1つずつConcurrentBagに商品を追加する必要があります。

3

送信側のデータにアクセスするために使用していたWebサービスが1つの大きなチャンクでタイムアウトしていたため、小さなチャンクを並行して処理しようとしても同様の問題が発生しましたが、各チャンクを連続的に処理する。レコードでのデータレコードの処理はさらに遅くなりました。私が呼んでいたサービスが大量の要求を処理できるため、タイムアウトなしにできるだけ多く送信する方がよいでしょう。

Vladと同じように、コンカレントバッグをオブジェクトタイプのリストに連結するとコンカレントバッグが返されないため、コンカットは機能しません。 (私はそれができないことを理解するのにはしばらく時間がかかりました)

代わりにList<T>を作成し、ConcurrentBag<List<T>>を作成してください。それぞれの並列反復では、並行バッグに新しいリストを追加します。並列ループが完了したら、ConcurrentBagをループし、可能な重複を排除したい場合は連結して、最初のList<T>に連結して、すべてを1つのリストに「平坦化」します。

+0

最後にSelectManyを使用して平坦化します。 –

17

(私はこれが古い投稿であることを知っています。

他の人が言ったように:はい、あなたは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)); 
    } 
関連する問題