ここでの以前の質問はすでに読みましたConcurrentBag
が、マルチスレッドでの実装の実際のサンプルは見つかりませんでした。
ConcurrentBag はスレッドセーフなバッグ実装であり、同じスレッドがバッグに格納されたデータの生成と消費の両方を行うシナリオに最適化されています。"
現在、私のコードでは次のように使用されています (これは実際のコードではなく簡略化されたものです)。
private void MyMethod()
{
List<Product> products = GetAllProducts(); // Get list of products
ConcurrentBag<Product> myBag = new ConcurrentBag<Product>();
//products were simply added here in the ConcurrentBag to simplify the code
//actual code process each product before adding in the bag
Parallel.ForEach(
products,
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
product => myBag.Add(product));
ProcessBag(myBag); // method to process each items in the concurrentbag
}
質問:
これは の正しい使い方ですか?このようなシナリオでConcurrentBag
使用しても大丈夫ですか?ConcurrentBag
私としては、シンプルで手動のロックの方が良いと思いますList<Product>
。その理由は、上記のシナリオがすでに「同じスレッドがバッグに保存されたデータの生成と消費の両方を行う。「ルール」です。
また、ThreadLocal
並列の各スレッドで作成されたストレージは、操作後も存在し続けることがわかりました(スレッドが再利用された場合でも、これは正しいですか?)。これにより、望ましくないメモリ リークが発生する可能性があります。
皆さん、私はこれで正しいですか?または、アイテムを削除する単純なクリアまたは空のメソッドでConcurrentBag
十分ですか?
ベストアンサー1
これは ConcurrentBag の適切な使用方法のように見えます。スレッド ローカル変数はバッグのメンバーであり、バッグと同時にガベージ コレクションの対象になります (内容をクリアしても解放されません)。ロック付きの単純なリストで十分だというのは正しいです。ループ内で行っている作業が重要なものであれば、スレッド同期の種類は全体的なパフォーマンスにはあまり影響しません。その場合は、使い慣れたものを使用する方が快適かもしれません。
もう一つの選択肢は並列列挙可能選択、これはあなたがやろうとしていることにもっと近いものです。繰り返しますが、あなたが目にするパフォーマンスの違いはおそらく無視できるほど小さいので、あなたが知っているものに固執しても何も問題はありません。
いつものように、このパフォーマンスが重要である場合は、実際に試して測定することに代わるものはありません。