2010-05-17 3 views
5

요청 당 정확히 하나의 숫자가 필요한 경우 ASP.NET MVC 응용 프로그램에서 난수를 생성하는 올바른 방법은 무엇입니까? MSDN에 따르면 충분한 품질의 무작위성을 얻으려면 한 번 생성 된 단일 System.Random 개체를 사용하여 여러 개의 숫자를 생성해야합니다. MVC의 각 요청에 대해 컨트롤러 클래스의 새 인스턴스가 만들어 지므로 컨트롤러의 생성자에서 임의 개체에 대해 초기화 된 전용 필드를 사용할 수 없습니다. 그래서 MVC 애플 리케이션의 어떤 부분에서 랜덤 객체를 생성하고 저장해야합니까? 현재 I 컨트롤러 클래스의 스태틱 필드에 저장하고 느리게 그것을 사용하는 동작 방식의 초기화 다음 "랜덤"필드가 컨트롤러 클래스의 다중 인스턴스에 액세스 할 수 있기 때문에MVC 응용 프로그램에서 난수 생성

public class HomeController : Controller 
{ 
    ... 

    private static Random random; 

    ... 

    public ActionResult Download() 
    { 
     ... 

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

     ... 

    } 
} 

를 그 것이다 두 인스턴스가 동시에 초기화하려고하면 값이 손상 될 수 있습니까? 그리고 또 하나의 질문 : 정적의 수명은 애플리케이션의 수명이라는 것을 알고 있습니다.하지만 MVC 앱의 경우에는 무엇입니까? IIS가 시작될 때까지 IIS가 종료됩니까?

답변

10

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으로 표시하지만 원칙을 보여줍니다.

1

HomeController에 정적 생성자를 사용하면 모든 메소드에서 초기화를 지연하지 않아도됩니다. 이것은 거의 Random이 단지 한번 초기화되는 것을 보장합니다 (그것이 처음 액세스 될 때).

당신은 몇 가지 빠른 데모 또는 뭔가를 함께 던져하지 않는 한
public class HomeController : Controller 
{ 
    ... 

    private static Random random; 

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

    ... 

    public ActionResult Download() 
    { 
     ... 

     //use random - its already created. 


     ... 

    } 
} 
2

, 나는 서비스 나 인프라 계층 (즉, 또 다른 클래스)에이 책임을 넣어 그것은 당신의 난수 발생기의 수명을 관리 할 수있다. 이 실제로이 컨트롤러를 관리하는 작업이 아닙니다. 임의의 숫자가 필요한 다른 컨트롤러가있는 경우에는 걱정할 필요가 없습니다.