我有一个运行时间较长(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秒。
我认为这是由于会话级别锁定引起的:
[如果]对同一会话发出两个并发请求(通过使用相同的SessionID值),则第一个请求将获得对会话信息的互斥访问。仅在第一个请求完成后才执行第二个请求。
因此,第二个请求在第一个请求完成之前无法访问会话。使用异步MVC操作似乎无法解决这个问题,因为该操作仍需要能够对会话进行更改。
是否可以在不使用AsyncController或的情况下停止一个动作并开始下一个动作[SessionState(SessionStateBehavior.ReadOnly)]?
AsyncController
[SessionState(SessionStateBehavior.ReadOnly)]
如果不是全部都需要?
事实证明,完整的答案需要两件事:
首先(感谢Darin确认),会话实际上锁定了要一个接一个执行的页面。进一步的调查表明,这是ASP.Net会话的一个更普遍的问题- 它们只是无法处理乐观并发。
其次,被取消的请求需要检查客户端是否仍然连接。在某些情况下,您可能希望继续执行操作(例如开火并忘记ASP操作),但是在这种情况下,如果客户不再等待报告,我们继续处理它就没有意义。
这是响应的属性:this.Response.IsClientConnected
this.Response.IsClientConnected
因此,要在jQuery请求时有效取消服务器端操作,我必须编写自己的会话处理程序并针对进行定期检查this.Response.IsClientConnected。