2012-01-20 39 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有關。但在這種情況下,我應該如何啓動用戶的當前文化?

回答

2

下面一行的問題是:

this.Session["Culture"] = ci; 

你寫會話。在ASP.NET中,會話不是線程安全的。出於這個原因ASP.NET synchronizes access它。這基本上意味着,如果您從同一會話的兩個並行請求中寫入到會話中的ASP.NET處理程序,ASP.NET將簡單地按順序執行它們。

不要誤解我的意思。這並不意味着來自2個不同用戶的兩個並行請求將被順序執行。它們將完全平行。只是假設你對這個控制器動作運行了2個並行的AJAX請求,並觀察了FireBug中的行爲或其他。由於這2個AJAX請求來自同一個會話,並且自從您寫入會話以來,您已遭到破壞,您的請求無法並行執行。

你將不得不尋找另一種處理文化的方式。餅乾或網址參數(更好的搜索引擎優化方面)可以作爲一個不錯的選擇。由於會議是不好的事情,擺脫它們只會有利於您的應用程序。

在ASP.NET MVC 3,你可以使用SessionState的屬性,並指示控制器動作將要麼不使用會話,否則會從它只能讀取:

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

} 

現在你可以擁有的並行處理來自同一屆會議的要求。顯然,每次嘗試寫入會話都會引發異常。

+0

這是一個非常好的綜合答案。謝謝! –