Asp.net-Mvc

MVC 應用程序中的隨機數生成

  • March 18, 2011

如果每個請求只需要一個數字,在 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 關閉嗎?

理想情況下,您希望將Random類的實例維護得比單個頁面的生命週期更長。不要它放在一個靜態變數中;該類Random不是執行緒安全的,這將導致問題。從文件

不保證任何實例成員都是執行緒安全的。

我最喜歡的方法是來自 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,但它說明了原理。

引用自:https://stackoverflow.com/questions/2847332