2012-01-18 93 views
9

我有一个长时间运行(4-10秒)的MVC动作,它运行AJAX调用的报告。在运行时,用户可以更改参数并运行其他内容,因此我在取消AJAX请求之前取消了另一个请求。如何取消AJAX长时间运行的MVC操作客户端(在JavaScript中)?

所以,举例来说(例如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

[如果]两个并发请求(通过使用 相同的SessionID值)为同一会议上提出的第一个请求到达 独占访问会话信息。第二个请求仅在 第一个请求完成后才执行。

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

如果不使用AsyncController[SessionState(SessionStateBehavior.ReadOnly)],可以停止一个动作并开始下一个动作吗?

如果不是都需要?

回答

4

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

首先(感谢达林对confirming it)会议基本上锁定要执行的页面一前一后。 Further investigation指出这是ASP.Net会话中更常见的问题 - 它们无法处理乐观并发。

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

这是作为一个property of the responsethis.Response.IsClientConnected

因此有效地消除我的服务器端操作时的jQuery要求它,我不得不写我自己的会话处理程序,并针对this.Response.IsClientConnected添加定期检查。

+1

要小心依靠'IsClientConnected',因为它可能显然是一个严重的性能问题来检查它,请参阅http://stackoverflow.com/questions/9094735/when-is-response-isclientconnected-slow – Keith 2012-02-29 14:09:25

+0

嗨基思!我有一个类似的问题,但不能解决它,即使你的答案,(http://stackoverflow.com/questions/29235850/how-to-abort-long-running-ajax-request-in-net-mvc-4 )有什么方法可以帮助我?或者你可以发布你的示例代码来触发'this.Response.IsClientConnected' – 2015-03-26 09:04:19

4

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

TPL具有内置的取消支持,您可以查看以简化这一操作,以避免在将它们同步的2之间共享数据结构。

+0

我已经在使用TPL来完成很多花费时间的工作 - 我正在大约4-10s的时间内执行大约25s长时间运行的连续代码。然而,使用它来处理中止似乎是重新发明轮子;为什么新的请求需要告诉旧的(仍在运行的)当它已经被取消时中止? – Keith 2012-01-19 08:33:13

+1

@凯斯,这不是新的要求会告诉老人放弃。您必须发送一个新的特殊AJAX请求来通知服务器放弃处理特定任务。当你做'dataRequest.abort();'你只是中止AJAX请求,但如果你想中止服务器端处理,你需要做的工作比这更多。 – 2012-01-19 08:36:26

+0

嗯,所以IIS不知道请求已在传输级别取消?我期望在等待连接在传输级别终止时页面线程在IIS/ASP级别中止。 – Keith 2012-01-19 08:40:31

1

.abort()只是客户端取消。如果你想在服务器端监控它,最好的方法之一是轮询IsClientConnected属性,它会告诉你什么是ajax通信的状态。

+1

查看接受的答案和原始问题。这个答案没有添加任何尚未陈述的内容。还要非常小心使用'IsClientConnected',因为它可能显然是一个严重的性能问题来检查它,请参阅http://stackoverflow.com/questions/9094735/when-is-response-isclientconnected-slow(显然它可能花费高达½s检查它,但没有人能够确认) – Keith 2012-02-29 14:18:35

+0

你是对的,我读过你的文章,我不得不修改我的解决方案。 – Dave 2012-02-29 15:09:15

相关问题