我想爲由AsyncController實現的長時間運行的請求提供進度監視機制。一個網頁所調用(通過JQuery $.post
)下面控制器上的異步StartTask動作...通過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();
}
}
}
同一網頁建立一個2秒定時器(經由window.setInterval)調用下面的控制器(通過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的稍微黑客解決方案)。
StartTask動作是否真的阻止?我認爲StartTaskAsync方法返回(我認爲這是我在調試器中觀察到的,將再次嘗試)並且ASP.NET工作線程返回到池,直到收到AsyncManager.OutstandingOperations.Decrement()調用(儘管如何ASP.NET MVC將調用Decrement()的線程與我不確定的相應XxxCompleted()動作方法相關聯。 StartTaskAsync不會阻止來自同一瀏覽器實例的對ProgressController.Current()的調用,只是ProgressController.Current()看不到相同的會話。 – 2011-01-31 21:35:08