Генерация случайных чисел в приложениях MVC

Каков корректный способ генерировать случайные числа в приложении 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?

5
задан SlimShaggy 17 May 2010 в 07:41
поделиться

3 ответа

В идеале вы хотите поддерживать экземпляр класса 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 , но он демонстрирует принцип.

10
ответ дан 18 December 2019 в 13:11
поделиться

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

public class HomeController : Controller
{
    ...

    private static Random random;

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

    ...

    public ActionResult Download()
    {
        ...

        //use random - its already created.


        ...

    }
}
1
ответ дан 18 December 2019 в 13:11
поделиться

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

3
ответ дан 18 December 2019 в 13:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: