2010-05-17 3 views
5

Каков правильный способ генерации случайных чисел в приложении ASP.NET MVC, если мне нужно точно одно число на запрос? Согласно MSDN, чтобы получить хаотичность достаточного качества, необходимо создать несколько номеров, используя один объект System.Random, созданный один раз. Поскольку для каждого запроса в MVC создается новый экземпляр класса контроллера, я не могу использовать приватное поле, инициализированное в конструкторе контроллера для объекта Random. Итак, в какой части приложения MVC я должен создавать и хранить объект Random? В настоящее время я хранить его в статическом поле класса контроллера и лениво инициализировать его в методе действий, который использует его:Генерация случайных чисел в приложениях MVC

public class HomeController : Controller 
{ 
    ... 

    private static Random random; 

    ... 

    public ActionResult Download() 
    { 
     ... 

     if (random == null) 
      random = new Random(); 

     ... 

    } 
} 

Поскольку поле «случайное» может быть доступно несколько экземплярами класса контроллера, это возможно ли его значение стать поврежденным, если два экземпляра попытаются его инициализировать одновременно? И еще один вопрос: я знаю, что срок службы статики - это время жизни приложения, но в случае приложения MVC, что это такое? Это от запуска IIS до закрытия IIS?

ответ

10

В идеале вы хотите сохранить экземпляр класса Random дольше, чем срок службы одной страницы. Do не сделать это, поставив его в статическую переменную; класс Random не является потокобезопасным, и это приведет к проблемам. От the docs:

Ни один из участников не гарантирует безопасность потолка.

Мой любимый подход класс RandomGen2 обертки из команды Microsoft ParallelFX (которые действительно знают, что они делают с резьбой), который использует экземпляр для каждого потока для (в основном) безблокировочных и поточно-случайных чисел ,

public static class RandomGen2 
{ 
    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(); 
    } 
} 

Что вы можете просто позвонить следующим образом:

var rand = RandomGen2.Next(); 

Вы можете добавить дополнительные методы, чтобы обернуть другие Random методы, которые вы хотите получить доступ, и я хотел бы предложить лучшее название такого как ThreadSafeRandom, но он демонстрирует принцип.

1

У вас может быть статический конструктор в HomeController, чтобы вы могли лениво инициализировать его в каждом методе. Это в значительной степени гарантирует, что Random будет инициализироваться только один раз (в первый раз, когда к нему обращаются).

public class HomeController : Controller 
{ 
    ... 

    private static Random random; 

    static HomeController() 
    { 
     random = new Random(); 
    } 

    ... 

    public ActionResult Download() 
    { 
     ... 

     //use random - its already created. 


     ... 

    } 
} 
2

Если вы не бросали вместе некоторые быстрые демо или что-то, я бы поставил эту ответственность в услуги или инфраструктуры слоя (то есть, только другой класс) и дайте ему управлять срок службы вашего генератора случайных чисел. Это не действительно задача контроллера, чтобы управлять этим в любом случае - и вы не будете беспокоиться об этом, когда/если у вас есть другой контроллер, которому требуется случайное число.

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