Каков корректный способ генерировать случайные числа в приложении MVC ASP.NET, если мне нужно точно одно число на запрос? Согласно MSDN, для получения случайности достаточного качества, необходимо генерировать несколько чисел с помощью единой системы. Случайный объект, созданный однажды. Так как новый экземпляр класса контроллера создается для каждого запроса в MVC, я не могу использовать частное поле, инициализированное в конструкторе контроллера для Случайного объекта. Таким образом в том, какая часть приложения MVC я должен создать и хранить Случайный объект? В настоящее время я храню его в статическом поле класса контроллера и лениво инициализирую его в методе действия, который использует его:
public class HomeController : Controller
{
...
private static Random random;
...
public ActionResult Download()
{
...
if (random == null)
random = new Random();
...
}
}
Так как к "случайному" полю могут получить доступ несколько экземпляров класса контроллера, для своего значения действительно ли возможно стать поврежденным, если два экземпляра пытаются инициализировать его одновременно? И еще один вопрос: Я знаю, что время жизни помех является временем жизни приложения, но в случае приложения MVC, что это? Это от запуска IIS до завершения работы IIS?
В идеале вы хотите поддерживать экземпляр класса Random
дольше, чем время жизни отдельной страницы. Разве не делают это, помещая это в статическую переменную; класс Random
не является потокобезопасным, и это приведет к проблемам. Из документы :
Никакие члены экземпляра не гарантированно будут потокобезопасными.
Мой любимый подход - это класс-оболочка 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();
Возможно, вам потребуется добавить дополнительные методы для обертывания других Случайных
методов, к которым вы хотите получить доступ, и я бы предложил более подходящее имя, например ThreadSafeRandom
, но он демонстрирует принцип.
У вас может быть статический конструктор в HomeController
, чтобы избавить вас от необходимости лениво инициализировать его в каждом методе. Это в значительной степени гарантирует, что Random
инициализируется только один раз (при самом первом обращении к нему).
public class HomeController : Controller
{
...
private static Random random;
static HomeController()
{
random = new Random();
}
...
public ActionResult Download()
{
...
//use random - its already created.
...
}
}
Если только вы не собираетесь сделать какую-нибудь быструю демонстрацию, я бы возложил эту ответственность на сервис или инфраструктурный уровень (т.е. просто другой класс) и позволил бы ему управлять временем жизни вашего генератора случайных чисел. Это не действительно работа контроллера, чтобы управлять этим в любом случае - и вам не придется беспокоиться об этом, когда/если у вас есть другой контроллер, которому нужно случайное число.