2012-01-20 3 views
1

ASP.NET MVC 3을 사용하고 있습니다. 일단 동기 동작 중 일부를 비동기 동작으로 변경하기로 결정했습니다. 이를 수행하기 전에 샘플 비동기 조치를 작성하여 제대로 작동하는지 테스트합니다. 이것은 다음과 같습니다 :비동기 작업으로 문화권 초기화하기

public void SampleAsync() 
    { 
     AsyncManager.OutstandingOperations.Increment(); 
     var task = System.Threading.Tasks.Task.Factory.StartNew(() => DoStuff()); 
     task.ContinueWith(t => 
     { 
      AsyncManager.Parameters["pars"] = t.Result; 
      AsyncManager.OutstandingOperations.Decrement(); 
     }); 
    } 

    private object DoStuff() 
    { 
     System.Threading.Thread.Sleep(20000); 
     return null; 
    } 

    public ActionResult SampleCompleted(object pars) 
    { 
     return View(); 
    } 

그러나이 작업은 비동기 적으로 작동하지 않았습니다! 그것은 절대적으로 동기식이었다. 적어도, 다른 요청 (실행 중)을 전통적인 작업으로 차단하고있었습니다. 조사의 몇 시간 후 나는 문제가 나는 현재의 문화를 초기화 한 내 asax 있다는 발견했습니다 :이 방법에서 주석 때

protected void Application_AcquireRequestState(object sender, EventArgs e) 
    { 
     CultureInfo ci; 
     //It's important to check whether session object is ready 
     if (HttpContext.Current.Session != null) 
     { 
      ci = (CultureInfo)this.Session["Culture"]; 
      //Checking first if there is no value in session 
      //and set default language 
      //this can happen for first user's request 

      if (ci == null) 
      { 
       ci = GetCultureFromCookie(); 
       this.Session["Culture"] = ci; 
      } 
      if (ci == null) 
      { 
       ci = GetStandardCulture(); 
       this.Session["Culture"] = ci; 
      } 
     } 
     else 
     { 
      ci = GetCultureFromCookie(); 
      if (ci == null) ci = GetStandardCulture(); 
     } 
     //Finally setting culture for each request 
     Thread.CurrentThread.CurrentUICulture = ci; 
     Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); 
    } 

는, 모든 것이 잘 작동하기 시작했다. 문제는 동작 완료 스레드에서 HttpContext.Current에 액세스하는 것과 관련 있다고 가정합니다. 그러나이 경우 사용자의 현재 문화를 어떻게 초기화해야합니까?

this.Session["Culture"] = ci; 

당신은 세션에 작성 :

답변

2

다음 줄은 문제입니다. ASP.NET에서는 세션이 스레드로부터 안전하지 않습니다. 이런 이유로 ASP.NET synchronizes access 그것에. 이것은 기본적으로 같은 세션에서 두 개의 병렬 요청 의 세션에 쓰는 ASP.NET 처리기를 실행하면 ASP.NET에서 순차적으로 실행한다는 것을 의미합니다.

잘못 이해하지 마세요. 이것은 2 명의 다른 사용자로부터의 두 개의 병렬 요청이 순차적으로 실행된다는 것을 의미하지는 않습니다. 그들은 완벽하게 평행 할 것입니다. 그것은 당신이이 컨트롤러 동작에 대해 2 개의 병렬 AJAX 요청을 실행했다고 가정하고 FireBug 또는 기타 동작을 관찰 한 것입니다. 2 개의 AJAX 요청은 동일한 세션에서 발생 했으므로 세션에 쓰고 나면 사용자가 파기되어 요청을 병렬로 실행할 수 없습니다.

문화를 다루는 또 다른 방법을 찾아야합니다. 좋은 대안으로 마음에 봄 쿠키 또는 URL 매개 변수 (SEO의 측면에서 더) 봄. 그리고 세션은 어쨌든 나쁜 것이므로, 제거하면 응용 프로그램에 도움이됩니다.

ASP.NET에서

MVC 3은 sessionState의이 컨트롤러 액션이 세션을 사용하지 않습니다 중 하나를 나타 내기 위해 속성을 사용할 수 있습니다 또는 그것은 단지 그것을 읽는됩니다 : 당신의 병렬 처리를 할 수 있습니다

이제
[SessionState(SessionStateBehavior.ReadOnly)] 
public class FooController: AsyncController 
{ 

} 

동일한 세션의 요청 분명히 세션에 쓰려고 할 때마다 예외가 발생합니다.

+0

아주 훌륭한 종합 답변입니다. 고맙습니다! –