2011-01-31 15 views
0

AsyncControllerによって実装された実行時間の長い要求に対して進捗監視メカニズムを提供しようとしています。 (jQueryの$.post経由)Webページが呼び出す、次のコントローラ上の非同期タスク開始のアクション...AJAX経由で呼び出されたコントローラ間の共有セッション状態アクセス

[NoAsyncTimeout] 
public class TaskController: AsyncController 
{ 
    [HttpPost] 
    public void StartTaskAsync() 
    { 
     AsyncManager.OutstandingOperations.Increment(); 
     Session["progress"] = "in progress"; 
     Task.Factory.StartNew(DoIt); 
    } 

    public ActionResult StartTaskCompleted() 
    { 
     return Json(new {redirectUrl = Url.Action("TaskComplete", "First")}); 
    } 

    private void DoIt() 
    { 
     try 
     { 
     // Long-running stuff takes place here, including updating 
     // Session["progress"]. 
     } 
     finally 
     { 
     AsyncManager.OutstandingOperations.Decrement(); 
     } 
    } 
} 

同じWebページには、以下のコントローラを(呼び出すために(window.setInterval経由)2秒タイマーを設定します読み取り専用のセッションへのアクセスをjQueryの$.getJSON)...

[SessionState(SessionStateBehavior.ReadOnly)] 
public class ProgressController: Controller 
{ 
    [HttpGet] 
    public ActionResult Current() 
    { 
     var data = Session["progress"]; 
     return Json(data, JsonRequestBehavior.AllowGet); 
    } 
} 

getJSONが戻った後呼び出される関数を経て現在の進行状況を表示するDIVを更新します。最終的に進捗状況は、「長時間実行されるものはここで発生します」コードによってセッション内で更新されますが、ProgressController.Current()への呼び出しはセッション内のデータを検出せず常にnullを返します。

同じブラウザから同じIISサーバーに送信されたJQuery AJAX要求が同じセッションで終了するとは思っていましたが、そうは思われません。これらの$ .postと$ .getJSON呼び出しで明示的にASP.NETセッションキーを設定する必要はありますか?または、コントローラ間でセッション状態を共有することはできません(R/Oアクセスを持っていても)。これは、アプリケーション状態とGUIDを持つややハッキリな解決策に戻すことができます。

答えて

0

これは正常な動作です。あなたのStartTaskアクションは完了するまでブロックされます。 DoItメソッドの実行が終了するまで、応答は返されません。私はそれがAJAX $.postでそれを呼び出す理由だと思います。問題は、このメソッドが実行されてセッションに書き込まれ、同じセッションからの他のすべての要求がASP.NETエンジンによってキューに入れられることです。セッションの書き込みと読み取りは同時にできません。セッション以外の進行状況データ用に、スレッドセーフな別のストレージを見つける必要があります。

+0

StartTaskアクションは実際にブロックしますか?私はStartTaskAsyncメソッドが返されたと思った(これは私がデバッガで観察したものだと思います)、ASP.NETワーカースレッドはAsyncManager.OutstandingOperations.Decrement()コールが受信されるまでプールに返されますASP.NET MVCは、Decrement()が呼び出されたスレッドを、わからない対応するXxxCompleted()アクションメソッドと関連付けます。 StartTaskAsyncは、同じブラウザインスタンスからProgressController.Current()への呼び出しをブロックしません。ProgressController.Current()は同じセッションを認識しません。 –

関連する問題