Asp.net-Mvc
MVC 應用程序中的隨機數生成
如果每個請求只需要一個數字,在 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,但它說明了原理。