2012-02-15 26 views
1

です。 ...はParallel.forEach(DataTable.AsEnumerable()スレッドセーフ

これらの列のいずれかがインデックス化されている場合
+1

「DataTable」は非常に複雑な獣です。 – SLaks

+0

複数のプロセッサにアプリケーションをデプロイするときに、私が推測してみましょう。愚かな答えかもしれません。 –

+1

"と仮定すると、' u'と 'mptions'の間違いが起きますか? Psst ..という言葉は "仮定"ではなく "仮定"である); – Jamiec

答えて

4

のDataRowクラスのdocumentationは決定的にこの型は、マルチスレッド読み取り操作に対して安全である

と述べています。 はすべての書き込み操作を同期させる必要があります。

それ以上は特定できません。

いずれにしても、Datatableへの並列書き込みは、おそらくうまくスケールされません。共有状態にアクセスする複数のスレッドがあり、単一のデータテーブルが非常に明白に共有状態である場合、スケーラビリティが低下します。さらに、NUMAハードウェアを使用しない限り、CPUコアは同じメモリバスへのアクセスを競合します。

並列処理(「その他のもの」)の結果を別の構造体(たとえばone of the concurrent collections)に戻し、ループが終了すると1つのスレッドから変更を適用する方がよいでしょう。

もう1つの方法は、PLINQを使用して結果を計算し、単純なforeachを使用してそれらを反復処理して、変更をDataTableに適用することです。

元のデータテーブルを完全に破棄し、必要なフィールドを含む新しいオブジェクトを返すことも、より良い解決策です。コードで結果をDataTableにする必要がない場合は、結果をIEnumerableとして返すことができます。

+0

私はあなたの答えを理解しています:たとえば、200行を含むデータテーブルの列Xを変更する必要がある場合、200行すべての列Xから値を取り出し、並行コレクションに格納してから、その同時収集で.For()を実行して値を変更し、単一スレッドでループして元のDataTableの列Xを同時収集の値から更新しますか? –

+0

いいえ、反対です。複数のスレッドから値を読み取っても問題ないので、それらを抽出する必要はありません。 200個の値を並行して処理する必要があると仮定すると、処理の結果を並行コレクションで収集してから、それらを単一のスレッドからテーブルに戻す必要があります。 –

+0

200は私が思った乱数だけでしたが、それはもっと多くのもののようでした。私の状況では、私はそのテーブルの1列が暗号化されているデータベースにテーブルを持っています。私はこのテーブルのすべての行をdbのDataTableにロードしてから、すべての行をループしてその列を解読する必要があります。私は値を同時に読み取って解読することができますが、元の行と列を更新するために、私はあなたのコメントを理解していると思います。 –

1

、それは間違いなく安全ではありません。
ない場合、それは安全かもしれないが、私はそうは思わない。

+0

「列が索引付けされている場合」とはどういう意味ですか?アクセスパターンは上に示したとおりです – Kumar

+0

@Kumar: 'DataTable'はSQL Serverと同様にインデックスを持っています。索引付けされた列を変更することは、行全体であっても安全ではありません。 – SLaks

+0

列のdefsは静的なので、フロントで心配する必要はありません.net 2を使用して構築されたアプリケーションの場合、perfファイルを推測するshdの方が良いでしょう.net 4 – Kumar

4

DataTableは、書き込み操作にスレッドセーフではありません。並行して行を変更すると、DataTableの状態が変更されるため、問題が発生します。

+0

は一般的ですが、各スレッドは異なる行で作業しているため、行自体には並行演算はありません。したがって、この特定のシナリオについての質問 – Kumar

+1

@Kumar各スレッドは別の行で作業していますが、この行に書き込み操作を行うと、DataTableの状態が影響を受けます。 – sarvesh

+0

具体的に影響を受けるものに関する詳細や説明はありますか? – Kumar

関連する問題