4

を使用して不明瞭な結果は、私はタスクを並列テストするには、このコードをC#で非同期プログラミングについての学習、および書かれてるライブラリ(コンソールアプリケーション):タスク - ランダム

static void Main(string[] args) 
{ 
    Stopwatch sw = new Stopwatch(); 

    var opr1 = new SlowOperation(); 
    var opr2 = new SlowOperation(); 

    //TASK 
    Console.WriteLine("Started processing using TASK. Start: {0}", sw.Elapsed); 
    sw.Start(); 

    Task.Factory.StartNew(() => opr1.PerformSlowOperation(1)); 
    Task.Factory.StartNew(() => opr2.PerformSlowOperation(2)); 

    Console.WriteLine("Stopped processing using TASK. Stop: {0}", sw.Elapsed); 
    sw.Stop(); 

} 

遅い操作は次のとおりです。

public class SlowOperation 
{ 
    public void PerformSlowOperation(int id) 
    { 
     var rand = new Random(); 
     double sum = 0; 

     for (int i = 0; i < 100000000; i++) 
     { 
      var number = Convert.ToDouble(rand.Next(100))/100; 
      sum += number; 
     } 
     Console.WriteLine("Finished processing operation no. {0}. Final sum calculated is: {1}", id, sum.ToString("0.##")); 
    } 
} 

SlowOperationクラスの各インスタンスによって生成された合計がまったく同じ理由を理解できたら助けてください。

+0

なぜあなたはたくさんのタスクを開始してすぐにストップウォッチを無効にし、それらが終了するまで待たずに終了したと言いますか? –

答えて

2

Randomは、低分解能で時間基準で播種される。これは古典的な問題であり、私の考えではAPI設計のエラーです。私はこれがすでにCoreCLRレポで変更されていると思います。

new Random().Next() == new Random().Next()はほぼ常に真です。

また、問題のコードの95%は問題とは関係ありません。将来は、ランダム呼び出しだけが残されるまでコードを簡単にすることができます。それであなたはそのような問題を自分で見つけることができます。

2

各タスクで異なるシード値を設定します。たとえば、次のように

var rand = new Random(new System.DateTime().Millisecond + id); 

ランダムコンストラクタ: はユニークなシード値がにある生産に

アプリケーションが異なる乱数列を必要とする場合https://msdn.microsoft.com/pt-br/library/ctssatww(v=vs.110).aspx、異なるシードvalues.Oneの方法で繰り返し このコンストラクタを呼び出しますたとえば、 はシステムクロックからシード値を取得します。ただし、システムクロック は、異なる呼び出しを行うために十分な解像度を持っていない可能性があります。 このコンストラクタのseエドの価値。

+2

'新しいRandom(new System.DateTime()。Millisecond)を呼び出すことは' new Random() 'を呼び出すことと変わりありません。基礎はまだミリ秒に基づいています。 – Enigmativity

+0

あなたは正しいです。私は不幸な例を与えました、私は私の答えを編集し、この例を削除します。 –