你如何取消AJAX长期运行的MVC动作客户端(在javascript中)?

时间:2012-01-18 17:40:42

标签: javascript asp.net ajax asp.net-mvc

我有一个长时间运行(4-10秒)的MVC操作,它运行来自AJAX调用的报告。虽然它正在运行的用户可以更改参数并运行其他内容,所以我在再创建一个AJAX请求之前取消它。

因此,例如(jQuery中的示例,但无论如何都会出现问题):

// If we have an active request and it's not complete
if(dataRequest && dataRequest.readyState != 'complete') 
{
    dataRequest.abort();
}

dataRequest = $.ajax(...);

客户端这似乎工作正常,但取消的请求仍在服务器上运行。例如,如果报告需要10秒,我取消一个并启动另一个,那么第二个请求需要20秒。

我认为这是由于session level locking

  

[If]为同一个会话发出两个并发请求(使用   相同的SessionID值),第一个请求获得独占访问权限   会话信息。第二个请求仅在执行后执行   第一个请求已经完成。

因此第二个请求无法访问会话,直到第一个请求完成。使用异步MVC操作似乎并没有解决这个问题,因为操作仍然需要能够对会话进行更改。

是否可以停止一个操作并在不使用AsyncController[SessionState(SessionStateBehavior.ReadOnly)]的情况下开始下一个操作?

如果不是都需要?

3 个答案:

答案 0 :(得分:4)

[SessionState(SessionStateBehavior.ReadOnly)]或完全禁用会话足以允许从同一会话并发访问控制器操作。所以第二个请求(来自同一个会话)不需要在处理之前等待第一个请求完成。至于取消服务器上的第一个操作,那就更难了。您必须将每个任务与唯一ID相关联,并在启动新任务时将此任务ID返回给客户端。然后,当您通过调用.abort()取消客户端上的AJAX请求时,您可以触发另一个AJAX请求到其他控制器操作并将其传递给唯一的任务ID。此控制器操作本身将设置一些公共标志以指示要停止的第一个操作。

TPL具有内置的取消支持,您可以对其进行简化,以避免在同步它们的2之间存在共享数据结构。

答案 1 :(得分:4)

事实证明,完整的答案需要两件事:

首先(感谢Darin confirming it)会话本质上会锁定要一个接一个地执行的页面。 Further investigation指出这是ASP.Net会话的一个更普遍的问题 - 他们只是无法处理乐观并发。

其次,取消的请求需要检查客户端是否仍然连接。在某些情况下,您可能希望继续(例如火灾并忘记ASP操作)但在这种情况下,如果客户端不再等待报告,那么我们就没有必要继续处理它。

这是以property of the responsethis.Response.IsClientConnected

提供的

因此,为了在jQuery请求时有效取消我的服务器端操作,我必须编写自己的会话处理程序并对this.Response.IsClientConnected添加定期检查。

答案 2 :(得分:1)

.abort()只是客户端取消。如果要在服务器端监视它,那么执行此操作的一个好方法是轮询 IsClientConnected 属性,该属性将告诉您ajax通信的状态。