2016-09-12 5 views
4

次のコードでは、配列の他のすべての要素だけが読み込まれているようです。どうして?Parallel.For要素をスキップする

Random rand = new Random(); 
int byteLength = 10000000; 
var result = new byte[10][]; 
Parallel.For(0, 10, (i) => 
{ 
    int length = rand.Next(byteLength); 
    var tempResult = new byte[length]; 
    Thread.Sleep(100); 
    rand.NextBytes(tempResult); 
    result[i] = tempResult; 
}); 

すべての要素を充填し、この(非平行)コードとは対照:MSDNでドキュメントのthe examplesに比較

rand = new Random(); 
var result2 = new byte[10][]; 
for (int i = 0; i < 10; i++) 
{ 
    int length = rand.Next(byteLength); 
    var tempResult = new byte[length]; 
    Thread.Sleep(100); 
    rand.NextBytes(tempResult); 
    result2[i] = tempResult; 
} 

、私はresultParallel.Forデリゲート外にあるためである疑い - したがって、resultにアクセスするとスレッドに問題があります。しかし、マルチスレッドの初心者として、私はこれが当てはまるとは思わない。

+4

複数のスレッドから「ランダム」のインスタンスを1つ使用しています。それは悪い考えです。「System.Random」はスレッドセーフではありません。それでも、すべての要素を埋める必要があります...あなたは正確に何を見ていますか? NULL参照、またはすべてのバイトが0のエントリだけ? –

+3

System.Randomはスレッドセーフではありません。 –

+0

System.Randomをご利用いただきありがとうございます。変更するとインスタンスが作成され、デリゲート内で問題が解決されるようです。誰でも答えとして書くように気をつけて、私は答えとしてマークしますか? –

答えて

1

Randomはスレッドセーフではありませんが(他のポスターから質問にコメントされているように)、反復変数iはRandoms returnの値に依存しないため、未使用のデータが表示される理由は疑問です。この場合、Randomは、スレッドが安全でない方法で呼び出されたときにゼロを返すと考えられ、データがいっぱいになっていないと判断して、空の配列があるだけです。これは、空ではない配列を最初に割り当て、ルーチンがそれをゼロ長に変更するかどうかを調べることによってテストできます。私はこれが「なぜ?」という完全な答えだと思います。

関連する問題