MVC 应用程序中的随机数生成

发布于 2024-09-01 18:38:15 字数 635 浏览 2 评论 0原文

如果每个请求只需要一个数字,那么在 ASP.NET MVC 应用程序中生成随机数的正确方法是什么?根据 MSDN,为了获得足够质量的随机性,有必要使用创建一次的单个 System.Random 对象生成多个数字。由于在 MVC 中为每个请求创建一个控制器类的新实例,因此我无法使用在控制器的构造函数中为 Random 对象初始化的私有字段。那么我应该在 MVC 应用程序的哪个部分创建和存储 Random 对象?目前,我将其存储在控制器类的静态字段中,并在使用它的操作方法中延迟初始化它:

public class HomeController : Controller
{
    ...

    private static Random random;

    ...

    public ActionResult Download()
    {
        ...

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

        ...

    }
}

由于“随机”字段可以由控制器类的多个实例访问,因此它的值是否有可能被损坏如果两个实例尝试同时初始化它?还有一个问题:我知道静态的生命周期就是应用程序的生命周期,但对于 MVC 应用程序来说它是什么?是从IIS启动到IIS关闭吗?

What is the correct way of generating random numbers in an ASP.NET MVC application if I need exactly one number per request? According to MSDN, in order to get randomness of sufficient quality, it is necessary to generate multiple numbers using a single System.Random object, created once. Since a new instance of a controller class is created for each request in MVC, I cannot use a private field initialized in the controller's constructor for the Random object. So in what part of the MVC app should I create and store the Random object? Currently I store it in a static field of the controller class and lazily initialize it in the action method that uses it:

public class HomeController : Controller
{
    ...

    private static Random random;

    ...

    public ActionResult Download()
    {
        ...

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

        ...

    }
}

Since the "random" field can be accessed by multiple instances of the controller class, is it possible for its value to become corrupted if two instances attempt to initialize it simultaneously? And one more question: I know that the lifetime of statics is the lifetime of the application, but in case of an MVC app what is it? Is it from IIS startup till IIS shutdown?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不醒的梦 2024-09-08 18:38:15

理想情况下,您希望维护 Random 类的实例的时间比单个页面的生命周期更长。不要通过将其放入静态变量中来实现此目的; Random 类不是线程安全的,这会导致问题。来自文档

不保证任何实例成员都是线程安全的。

我最喜欢的方法是 Microsoft 的 RandomGen2 包装类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 code>,但它演示了原理。

Ideally you want to maintain an instance of the Random class for longer than the lifetime of a single page. Do not do this by putting it in a static variable; the Random class is not thread-safe and this will result in problems. From the docs:

Any instance members are not guaranteed to be thread safe.

My favourite approach is the RandomGen2 wrapper class from the Microsoft ParallelFX team (who really know what they're doing with threading) which uses an instance per thread for (mostly) lock-free and thread-safe random numbers.

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(); 
    } 
}

Which you can then just call as follows:

var rand = RandomGen2.Next();

You may need to add extra methods to wrap the other Random methods you want to access, and I'd suggest a better name such as ThreadSafeRandom, but it demonstrates the principle.

烟若柳尘 2024-09-08 18:38:15

除非您将一些快速演示或其他东西放在一起,否则我会将这个责任放入服务或基础设施层(即,只是另一个类)中,并让它管理随机数生成器的生命周期。无论如何,管理这个问题并不是控制器的工作 - 当/如果您有另一个需要随机数的控制器时,您将不必担心它。

Unless you're throwing together some quick demo or something, I would put this responsibility into a service or infrastructure layer (ie, just another class) and let it manage the lifetime of your random number generator. It's not really the controller's job to manage this anyway - and you won't have worry about it when/if you have another controller that needs a random number.

岁月无声 2024-09-08 18:38:15

您可以在 HomeController 中有一个静态构造函数,这样您就不必在每个方法中延迟初始化它。这几乎可以确保 Random 仅初始化一次(第一次访问时)。

public class HomeController : Controller
{
    ...

    private static Random random;

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

    ...

    public ActionResult Download()
    {
        ...

        //use random - its already created.


        ...

    }
}

You could have a static contructor in HomeController to save you having to lazy initialize it in every method. This pretty much ensures that the Random only gets initialised once (the very first time it's accessed).

public class HomeController : Controller
{
    ...

    private static Random random;

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

    ...

    public ActionResult Download()
    {
        ...

        //use random - its already created.


        ...

    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文