【问题标题】:Random number generation in MVC applicationsMVC 应用程序中的随机数生成
【发布时间】:2010-05-17 07:41:52
【问题描述】:

如果每个请求只需要一个数字,在 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 关闭吗?

【问题讨论】:

    标签: asp.net-mvc random static-members


    【解决方案1】:

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

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

    我最喜欢的方法是来自 Microsoft ParallelFX 团队的RandomGen2 包装器类(他们真的知道他们在用线程做什么),它使用每个线程的实例来处理(大部分)无锁和线程安全的随机数。

    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,但它说明了原理。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        您可以在HomeController 中有一个静态构造函数,以节省您在每个方法中都必须懒惰地初始化它。这几乎可以确保 Random 只被初始化一次(第一次被访问)。

        public class HomeController : Controller
        {
            ...
        
            private static Random random;
        
            static HomeController()
            {
                random = new Random();
            }
        
            ...
        
            public ActionResult Download()
            {
                ...
        
                //use random - its already created.
        
        
                ...
        
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2011-02-25
          • 2015-04-20
          • 2020-06-07
          • 2017-02-24
          • 1970-01-01
          • 1970-01-01
          • 2016-09-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多