c# - 在 ASP.NET MVC 中通过 CancellationToken 中止 AJAX 请求

标签 c# asp.net-mvc task-parallel-library asp.net-ajax cancellation

我有一个与外部资源交互的 ASP.NET MVC 应用程序,并且有一个操作需要花费很多时间。 所以在 Controller 中我有这样的方法

[HttpPost]
public async Task<JsonResult> SomeMethod(..., CancellationToken token)
{
    await _someService.ExecuteSlowOperationAsync(..., token);
    ...
}

而这个缓慢的操作看起来像

public async Task ExecuteSlowOperationAsync(..., CancellationToken token)
{
    return await Task.Run(() => 
    {
       //interacting with external resource
    }, token);
} 

此方法与模态视图相关联,如果请求需要很长时间,用户可能会决定关闭它。据此我必须在不等待结果的情况下取消请求,所以在客户端我有类似的代码

...
var request = $.ajax(...);

...

$('#modal').on('hidden.bs.modal', function () {
  request.abort();
});

如果我理解这个article正确地,取消 token 通过框架模型绑定(bind)器与请求绑定(bind),无需对其进行任何操作。当用户关闭模态表单时,在浏览器控制台中我可以看到请求状态为“已取消”,但在服务器端缓慢的操作仍在执行。 Aslo 我试过了

CancellationToken disconnectedToken = Response.ClientDisconnectedToken;            
var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, disconnectedToken);

然后从这个来源获取 token ,但仍然一无所获。

我觉得我错过了一些重要的东西,对这种情况有误解。有什么想法可以让它发挥作用吗?

最佳答案

我的回答可能有点晚了。但我想我发现了你的问题。使用 Task.Run(Action action, CancellationToken cancellationToken) 取消长时间运行的操作可能并不总是有效。

Using CancellationToken for timeout in Task.Run does not work

如果长时间运行的操作在你自己的代码中,你应该这样写

public async Task ExecuteSlowOperationAsync(..., CancellationToken token)
{
    while (true)
    {
        if(cancelToken.IsCancellationRequested)
        {
            return;
        }
        ...
    }
}

如果您无法修改长时间运行的操作本身的源代码,您可以使用来自Microsoft.VisualStudio.Threading.ThreadingToolsWithCancellation (有关更多信息,请参阅 https://stackoverflow.com/a/33396646/9483821)您甚至可以更早地在您的 Controller 上使用它

[HttpPost]
public async Task<JsonResult> SomeMethod(..., CancellationToken token)
{
     CancellationToken disconnectedToken = Response.ClientDisconnectedToken;            
     var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, disconnectedToken).Token;
     await _someService.ExecuteSlowOperationAsync(...).WithCancellation(linkedToken);
     ...
}

关于c# - 在 ASP.NET MVC 中通过 CancellationToken 中止 AJAX 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50614643/

相关文章:

sql-server - 无法从 diff Web 角色中的本地数据库获取数据

c# - Task.Factory.StartNew() 生成对象未初始化错误

c# - 我怎样才能优化这个正则表达式的性能?

c# - 单例 - if 或 try/catch?

c# - GroupBy 复杂查询

c# - 在 Parallel.ForEach 中嵌套 await

c# - 与上一个线程在同一线程中的继续任务

c# - byte[] 到 bool[] 用作标志,反之亦然

python - ASP.NET MVC 上的 IronPython

javascript - Select2 框包含不需要的文本