2015-05-13 1 views
2
public TestClass{ 

    public Task<int> GetRandomNumber() { 
       return Task.FromResult(new Random().Next(0, 1500)); 
      } 
    } 



public class Default 
    { 
     static void Main(string[] args) 
     { 
      var test = new TestClass(); 
      List<int> adddata = new List<int>(); 
      for (int i = 0; i < 3; i++) 
      { 
       var result = Task.Run(() => test.GetRandomNumber()); 
       Console.WriteLine("The values that will be added are :{0}", result.Result); 
       adddata.Add(result.Result);  
      } 
      Console.WriteLine("The value is :{0}", adddata.Sum(v => v)); 
    } 
} 

Проблема случайного числа возвращает одинаковые числа, 68, 68, 122, когда он должен возвращать отличное число, что я делаю неправильно. Я пытаюсь узнать, как использовать задачу в C# .THANKS!Добавить числа путем генерации случайных задач, содержащих числа

+0

КПП. даже если вы каждый раз не создаете новый объект «Случайный» (и не решаете проблему безопасности потока), «случайный» по-прежнему не означает «уникальный». Таким образом, все еще могут быть некоторые номера (время от времени). Если вам нужны * уникальные * случайные числа, обычный подход состоит в том, чтобы иметь все возможные числа в пуле, а затем случайным образом принимать (и удалять) числа из этого пула. В вашем случае введите новый список (Enumerable.Range (0, 1500)) 'и идите оттуда. – Corak

ответ

4

Потому что каждый раз вы генерируете новый экземпляр Random. Создайте объект Random один раз. Как Random не поточно, мы должны использовать генератор случайных чисел, который:

public static class ThreadSafeRandom 
{ 
    private static Random global = new Random(); 

    [ThreadStatic] 
    private static Random local; 

    public static int Next() 
    { 
     Random inst = local; 
     if (inst == null) 
     { 
      int seed; 
      lock (global) 
      { 
       seed = global.Next(); 
      } 

      local = inst = new Random(seed); 
     } 

     return inst.Next(); 
    } 
} 

А теперь потреблять:

public TestClass 
{ 
    public Task<int> GetRandomNumber() 
    { 
     return Task.FromResult(ThreadSafeRandom.Next()); 
    } 
} 

Edit:

В стороне Обратите внимание, что вы выполняете свой делегат в потоке threadpool и сразу же синхронно блокируете его с помощью Result. Я предполагаю, что вы хотите сделать, это выполнить их в параллель:

static void Main(string[] args) 
{ 
    var test = new TestClass(); 

    Task<int>[] addData = Enumerable.Range(0, 4) 
            .Select(_ => Task.Run(() => test.GetRandomNumber())) 
            .ToArray(); 

    Task.WaitAll(addData); 
    foreach (var result in addData) 
    { 
     Console.WriteLine("The values that will be added are :{0}", result.Result); 
    } 

    Console.WriteLine("The value is :{0}", adddata.Select(x => x.Result).Sum()); 
} 

Edit 2:

Согласно @ChrisL правильно указывая Random не поточно, я модифицировал код для использования беспорядочного случайного генератора, предоставленного the PFX team.

+1

В статье msdn, которую я связывал, это обычное и неправильное решение - эта статья ошибочна? –

+1

@ChrisL Ты прав. Юваль правильно указывает, что OP генерирует экземпляры «Random» в быстрой последовательности, но, как указывает ваш ответ, генерация одного экземпляра, разделяемого всеми потоками, также не является правильным решением. – dcastro

+0

@ChrisL Ты прав. Я изменил код с помощью поточно-безопасного генератора, предоставленного командой PFX. Спасибо, что указали, что я тоже кое-что узнал :) –

0

Посмотрите на этот пост здесь: Thread safe random number generation

Короче: Random() не поточно и не было разработано, чтобы быть.

+0

Экземпляры «Random», которые он создает, являются локальными, они не используются. – dcastro

+0

@dcastro Вы правы, я не обратил на это внимания. Благодарю. –

Смежные вопросы