我正在尝试为AsyncController实现的长期运行请求提供进度监视机制。一个网页调用(通过JQuery $.post
)以下控制器上的异步StartTask操作......
[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的轻微hacky解决方案)。
答案 0 :(得分:0)
这是正常行为。您的StartTask
操作会一直阻止,直到完成为止。在DoIt
方法执行完毕之前,它不会返回任何响应。我想这就是你用AJAX $.post
调用它的原因。问题是,当此方法运行并写入会话时,来自同一会话的所有其他请求将由ASP.NET引擎排队。您无法同时在会话中进行写入和读取。除了会话之外,您还必须为进度数据找到另一个线程安全存储。