2017-06-03 7 views
-1

私はparallel.foreachループを使用する長い実行プロセスがあります。このループでは、渡される内容に基づいて2つの異なるクラスのインスタンスを作成し、マイナーなタスクを実行してから、スレッドセーフなコレクションに追加します。完了したら、すべてのデータをsqlに挿入する必要があります。スレッドセーフなコレクションをクリア中にparallel.foreachループをSQLに挿入した後

問題は、すべての処理が完了するまで、完了した作業量が大きすぎてコレクションに収まらないことです。 SQLに保持されているものを時々プッシュしてコレクションからプッシュされたものを削除しなければならないので、メモリ不足で処理を続けることができ、そのための最善の方法はわかりません。コレクションの数をチェックしてマルチスレッドでなくても、それが一定量を超えている場合は、一括挿入または値付き表を使用して内容をSQLにプッシュし、そのコレクションをクリアする関数を呼び出してください次の声明で。 parallel.foreachの中でこれを達成する最良の方法は何ですか?

私はスレッドセーフなコレクションを使用しています。今のところ私はConcurrentQueueを使用していて、BlockingCollectionに切り替えることを考えました。なぜなら、同時キューをクリアする方法がないからです。私は内容がどのような順序で挿入されても構わないが、SQLにプッシュされているものを少なくとも削除できる必要がある。

ベストソリューションはBlockingCollection.GetConsumingEnumerable()です。この方法で、一度x量を超えると、そのコレクションの内容を別のスレッドセーフなコレクションにコピーし、挿入を実行してから、そのリストを使用してオリジナルから削除することができます。BlockingCollection.GetConsumingEnumerable()。それが終わったら、一時リストを破棄してください。私はちょうど良い方法があると思った。なぜなら、一度に1つずつ削除しなければならないと、それはマルチスレッド化の目的を破るからだ。

私はpulse and waitの使用を見ましたが、安全だと思われる良いユースケースは見つかりませんでした。特定の量を超えるコレクションをテストした後、SQLに挿入される前にクリアされた後、何かが発生する可能性があります。

私は4.5フレームワークを使用しています。私はプッシュする必要があるが必ずしも同じではない2つの異なるコレクションを管理しています。

+1

[TPL Dataflow](https://www.google.co.uk/search?q=microsoft+tpl+dataflow)をご覧ください。これには、プロデューサ/コンシューマフローをプログラムで調整するために必要なすべてのビルディングブロックが含まれています。あなたが説明している問題に非常によく似ているようです。それが提供しているものを見るために小さな迂回路を取る。あなたはそれを後悔しません。 – spender

答えて

1

同時収集をクリアすることはお勧めしません。代わりに、私はそれを新しいものに置き換えて、古いものからのコンテンツを処理し、他のスレッドは新しいコンテンツにコンテンツをプッシュします。

Interlocked.Exchange私がこれを達成するために使用する技術です。

関連する問題