异步控制器通过jQuery阻止ASP.NET MVC中的请求
我刚刚开始在我的项目中使用AsyncController来处理一些长时间运行的报告。 因为我可以启动报告然后执行一些其他操作,同时等待它返回并在屏幕上填充元素,这似乎很理想。
我的控制器看起来有点像这样。 我试图使用一个线程执行长任务,我希望释放控制器以获取更多请求:
public class ReportsController : AsyncController { public void LongRunningActionAsync() { AsyncManager.OutstandingOperations.Increment(); var newThread = new Thread(LongTask); newThread.Start(); } private void LongTask() { // Do something that takes a really long time //....... AsyncManager.OutstandingOperations.Decrement(); } public ActionResult LongRunningActionCompleted(string message) { // Set some data up on the view or something... return View(); } public JsonResult AnotherControllerAction() { // Do a quick task... return Json("..."); } }
但我发现,当我使用jQuery ajax请求调用LongRunningAction时,我之后做的任何进一步请求都会在它后面备份,直到LongRunningAction完成才会处理。 例如,调用LongRunningAction需要10秒,然后调用不到一秒的AnotherControllerAction。 AnotherControllerAction只是在返回结果之前等待LongRunningAction完成。
我还检查了jQuery代码,但如果我专门设置“async:true”,这仍然会发生:
$.ajax({ async: true, type: "POST", url: "/Reports.aspx/LongRunningAction", dataType: "html", success: function(data, textStatus, XMLHttpRequest) { // ... }, error: function(XMLHttpRequest, textStatus, errorThrown) { // ... } });
目前我不得不假设我使用不正确,但我希望你们中的一个能清除我的精神障碍!
这里有两个问题。 首先,您的控制器不是真正的异步。 启动ThreadPool线程来执行工作通常具有比在Action方法本身中执行所有操作更糟糕的性能特征,因为您仍然从ASP.NET(它只是共享CLR ThreadPool)获取ThreadPool资源, 而您现在强制CLR和操作系统处理线程。 有关更多信息,请参阅http://msdn.microsoft.com/en-us/library/ee728598.aspx#choosing_synchronous_or_asynchronous_action_methods 。 基本上,该链接归结为如果您不能使用I / O完成端口进行异步操作,则不太可能看到性能提升。
第二个问题是ASP.NET MVC对所有请求进行会话锁定。 单个会话中的多个请求将始终被序列化,否则如果一个控制器写入Session而另一个控制器正在尝试读取它,则用户的会话可能会损坏。 有关上下文和解决方法,请参见http://forums.asp.net/t/1501623.aspx 。 MVC 2 Futures有一种禁用此锁的方法; 它也可能包含在MVC 3中。 有关详细信息,请参阅https://blogs.msdn.com/b/rickandy/archive/2009/12/17/session-less-mvc-controller.aspx 。
实际上问题在于.HttpContext.Session,’因为它被锁定,如果你在AsyncController中为会话写任何东西,你应该避免它并使用this.HttpContext.Application – 这将解决问题,我有同样的问题,并试试我们