Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何取消AJAX长期运行的MVC操作客户端(javascript)?_Javascript_Asp.net_Ajax_Asp.net Mvc - Fatal编程技术网

如何取消AJAX长期运行的MVC操作客户端(javascript)?

如何取消AJAX长期运行的MVC操作客户端(javascript)?,javascript,asp.net,ajax,asp.net-mvc,Javascript,Asp.net,Ajax,Asp.net Mvc,我有一个长时间运行(4-10秒)的MVC操作,它运行来自AJAX调用的报告。当它运行时,用户可以更改参数并运行其他内容,因此我在发出另一个AJAX请求之前取消了AJAX请求 因此,例如(例如在jQuery中,但无论如何问题都会发生): 客户端这似乎工作正常,但已取消的请求仍在服务器上运行。例如,如果报告需要10秒,我取消一个并启动另一个,那么第二个请求需要20秒 我认为这是由于: [如果]针对同一会话发出两个并发请求(通过使用 相同的SessionID值),第一个请求以独占方式访问 会话信息。第

我有一个长时间运行(4-10秒)的MVC操作,它运行来自AJAX调用的报告。当它运行时,用户可以更改参数并运行其他内容,因此我在发出另一个AJAX请求之前取消了AJAX请求

因此,例如(例如在jQuery中,但无论如何问题都会发生):

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

我认为这是由于:

[如果]针对同一会话发出两个并发请求(通过使用 相同的SessionID值),第一个请求以独占方式访问 会话信息。第二个请求仅在 第一个请求完成了

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

是否可以停止一个操作并启动下一个操作,而不使用
AsyncController
[SessionState(SessionStateBehavior.ReadOnly)]

如果不是,则两者都是必需的?

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


具有内置的取消支持,您可以查看以简化该功能,以避免2之间的共享数据结构将它们同步。

因为完整的答案需要两件事:

首先(感谢Darin),会话本质上锁定了一个接一个执行的页面。已经指出这是ASP.Net会话的一个更普遍的问题——它们无法处理乐观并发

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

这可以通过以下方式获得:
This.Response.IsClientConnected


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

。abort()只是客户端取消。如果您想在服务器端监视它,一个好方法是轮询IsClientConnected属性,它将告诉您ajax通信的状态

我已经在使用TPL来做很多需要花费时间的工作——我正在以大约4-10秒的并行速度执行大约25秒的长时间连续运行的代码。然而,使用它来处理中止看起来确实像是重新发明轮子;当新请求已经被取消时,为什么新请求需要告诉旧请求(仍在运行)中止?@Keith,告诉旧请求中止的不是新请求。您必须发送一个新的特殊AJAX请求,通知服务器中止对特定任务的处理。当您执行
dataRequest.abort()时您只是在中止AJAX请求,但是如果您想中止服务器端处理,您需要做更多的工作。嗯,所以IIS不知道该请求已在传输级别被取消?当等待的连接在传输级别终止时,我希望页面线程在IIS/ASP级别中止。IIS确实如此-我需要做的只是在长时间运行的页面中检查
响应。IsClientConnected
。当该属性变为false时,我将取消我正在执行的操作。请小心依赖
IsClientConnected
,因为检查它显然会导致严重的性能问题,请参见Hi Keith!我有一个类似的问题,但即使有你的答案也无法解决,()有什么办法帮我吗?或者您可以发布一个示例代码来触发
this.Response.IsClientConnected
查看接受的答案和原始问题。这个答案没有添加任何尚未声明的内容。使用
IsClientConnected
时也要格外小心,因为检查它显然会带来严重的性能问题,请参见(显然,检查它可能需要花费½s的时间,但没有人能够确认)您是对的,我已经阅读了您的帖子,我必须修改我的解决方案。
// If we have an active request and it's not complete
if(dataRequest && dataRequest.readyState != 'complete') 
{
    dataRequest.abort();
}

dataRequest = $.ajax(...);