0

VS2010 Concurrency Profilerからの出力を見ていて、いくつかのLINQオペレーターの周りでいくつかのスレッド競合が発生していることに気付きました。競合を引き起こしているステートメントは次のとおりです。

m_dictionary.PermutableSubunits.Select(subunit => subunit.Number).ToArray()

LINQオペレーターはブロックしますか?Parallel.ForEachの一部として実行されているタスクでそれらを使用する場合はもっと注意する必要がありますか?

4

2 に答える 2

2

LINQ to Objectsについて質問していると思います。したがって、コード内のSelect呼び出しはEnumerable.Select(..)に対応します。

LINQ to Objectsオペレーター自体は、実行中のスレッドを明示的にブロックしません。ただし、メモリは割り当てられます。たとえば、ToArray演算子は、結果をバッファリングするために、ますます大きな配列を割り当てます。

また、メモリの割り当てにより、スレッドがブロックされる可能性があります。メモリを割り当てるとき、CLRまたはOSは、空きメモリのチャンクを見つけるためにロックを取得する必要がある場合があります。さらに重要なことに、CLRは、メモリを割り当てるたびにガベージコレクション(GC)を実行することを決定する可能性があり、その結果、スレッドが大幅にブロックされる可能性があります。

サーバーGCがアプリケーションに適している場合は、サーバーGCをオンにして、スループットが向上するかどうかを確認できます。また、多くの場合、LINQtoObjectsクエリよりも少ないメモリ割り当てを実行する非LINQコードを記述できます。あなたの特定の例では、LINQ to Objectsは結果を小さな配列に生成し始め、結果が収まらないときはいつでも大きな配列を割り当てると思います。カスタム実装では、最初から適切なサイズの配列を割り当てて、大量の不要な割り当てを回避できる場合があります。

于 2011-04-26T18:53:05.827 に答える
0

ブロックするべきではありませんが、Linq-to-SQLを使用している場合、クエリの実行に長い時間がかかると、非常に長い時間がかかる可能性があります...一般的に、マルチスレッドで何かをしているときはいつでも「もっと注意してください」または彼らが言うように:「慎重に通してください!」

ただし、競合の問題が発生している場合は、実際に行っていることを実際に分析する必要があります。Linqはスレッドセーフではないため、別のスレッドから変更される可能性のあるエンティティに対して読み取り/書き込み操作を実行している場合は、適切に同期する必要があります。

于 2011-04-17T09:40:13.440 に答える