我们是否应该在MVC/Web API控制器中使用CancellationToken?

57

有不同的异步控制器示例。其中一些在方法定义中使用CancellationToken:

public async Task<ActionResult> ShowItem(int id, CancellationToken cancellationToken)
{
    await Database.GetItem(id, cancellationToken);
    ...

但是其他示例甚至VS2013的默认ASP.NET项目根本不使用CancellationToken,并且可以在没有它的情况下正常工作:

public async Task<ActionResult> ShowItem(int id)
{
    await Database.GetItem(id);
    ...

我们不确定是否应该在控制器中使用CancellationToken(以及为什么)。

3个回答

58

您应该使用它。目前它仅适用于如果您有一个AsyncTimeout,但很可能未来的MVC/WebAPI版本将把该令牌解释为“超时或客户端断开连接”。


1
Web API在取消令牌和断开连接的客户端方面的情况是否有所改变? - Drew Noakes
据我所知,目前还没有解决。我相信这将在ASP.NET vNext中得到修复。 - Stephen Cleary
17
我刚在VS 2015下测试了它,并且在浏览器中点击停止确实会触发取消令牌。 - Jonathan Allen
你如何将 Cancellation Token 从 C# Web 客户端传递到 Get API 方法?你如何将取消令牌序列化为 URL 字符串? - eesh
1
@eesh:我根本不会尝试那样做。相反,考虑在触发取消令牌时让客户端关闭连接,并将取消令牌作为参数传递给服务器(由WebAPI自动提供,并在连接断开时取消)。 - Stephen Cleary
显示剩余6条评论

8
用户可以随时通过在浏览器上点击停止或重新加载按钮来取消对您的Web应用程序的请求。通常,即使Kestrel不将其发送给用户,您的应用程序仍将继续生成响应。如果您有一个长时间运行的操作方法,则可能希望检测何时取消请求并停止执行。
您可以通过将CancellationToken注入到操作方法中来实现此目的,该令牌将自动绑定到请求的HttpContext.RequestAborted令牌。您可以像往常一样检查此令牌是否已取消,并将其传递给支持它的任何异步方法。如果请求被取消,将抛出OperationCanceledException或TaskCanceledException。
以下链接详细解释了这种情况。

https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/


在单页应用程序(SPAs)中使用Ajax请求? - jenson-button-event

8

你可以使用这个

public async Task<ActionResult> MyReallySlowReport(CancellationToken cancellationToken)
{
    CancellationToken disconnectedToken = Response.ClientDisconnectedToken;
    using (var source = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, disconnectedToken))
    {
        IEnumerable<ReportItem> items;
        using (ApplicationDbContext context = new ApplicationDbContext())
        {
            items = await context.ReportItems.ToArrayAsync(source.Token);
        }
        return View(items);
    }
}

taken from here.


2
你必须处理LinkedTokenSource,因为它不会被GC回收,这会导致内存泄漏。MSDN:请注意,在使用完后,必须调用Dispose释放链接的令牌源。http://msdn.microsoft.com/en-us/library/dd997364.aspx - Miles
根据参考资料,为使取消标记与MVC 5一起工作,需要执行以下步骤:“……由于某些原因,仅当您使用AsyncTimeout属性时,MVC 5才支持取消操作。”文章指出:“在ASP.NET Core MVC和Web API中,所有内容都按预期工作……”也就是说,如果您使用的是.NET Core,则只需要像往常一样传递Cancellation Token即可。 - SeanStanden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接