我们应该将 CancellationToken 与 MVC/Web API 控制器一起使用吗?
Posted
技术标签:
【中文标题】我们应该将 CancellationToken 与 MVC/Web API 控制器一起使用吗?【英文标题】:Should we use CancellationToken with MVC/Web API controllers? 【发布时间】:2013-10-01 09:29:33 【问题描述】:异步控制器有不同的示例。其中一些在方法定义中使用了 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(以及为什么)。
【问题讨论】:
【参考方案1】:你应该使用它。目前它仅适用于if you have an AsyncTimeout
,但未来的 MVC/WebAPI 版本可能会将令牌解释为“超时或客户端断开连接”。
【讨论】:
Web API 的情况在取消令牌和断开连接的客户端方面是否发生了变化? @DrewNoakes:AFAIK 它还没有。我相信这将在 ASP.NET vNext 中得到解决。 我刚刚在 VS 2015 下对其进行了测试,在浏览器中点击停止确实触发了取消令牌。 如何将取消令牌从 C# Web 客户端传递到 Get API 方法?如何将取消令牌序列化为 URL 字符串? @eesh:我根本不会尝试。相反,请考虑在触发取消令牌时让客户端关闭其连接;并让服务器将取消令牌作为参数(由 WebAPI 自动提供并在连接断开时取消)。【参考方案2】:你可以用这个
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);
取自here。
【讨论】:
你必须处理 LinkedTokenSource 因为它永远不会被 GC 收集,它会导致内存泄漏。 MSDN:请注意,完成后必须在链接的令牌源上调用 Dispose。 msdn.microsoft.com/en-us/library/dd997364.aspx 根据参考,需要这个过程才能使取消令牌与MVC 5一起工作; “...出于某种原因,MVC 5 仅在您使用 AsyncTimeout 属性时才支持取消。”。文章指出“在 ASP.NET Core MVC 和 Web API 中,一切都按预期工作......”。即,如果您使用的是 .NET Core,那么您只需要照常传递 CancellationToken。【参考方案3】:用户可以随时取消对您的网络应用程序的请求,方法是点击浏览器上的停止或重新加载按钮。通常,您的应用程序将继续生成响应,即使 Kestrel 不会将其发送给用户。如果您有一个长时间运行的操作方法,那么您可能希望检测何时取消请求并停止执行。
您可以通过将 CancellationToken 注入到您的操作方法中来执行此操作,该操作方法将自动绑定到请求的 HttpContext.RequestAborted 令牌。您可以像往常一样检查此令牌是否取消,并将其传递给任何支持它的异步方法。如果请求被取消,会抛出 OperationCanceledException 或 TaskCanceledException。
下面的链接详细解释了这种情况。
https://andrewlock.net/using-cancellationtokens-in-asp-net-core-mvc-controllers/
【讨论】:
和 SPA 中的 ajax 请求?以上是关于我们应该将 CancellationToken 与 MVC/Web API 控制器一起使用吗?的主要内容,如果未能解决你的问题,请参考以下文章
我应该如何使用 DataflowBlockOptions.CancellationToken?
我应该何时调用 CancellationToken.ThrowIfCancellationRequested?
C# CancellationToken 如何与 SqlConnection.OpenAsync(token) 一起使用?