【问题标题】:Should we use CancellationToken with MVC/Web API controllers?我们应该将 CancellationToken 与 MVC/Web API 控制器一起使用吗?
【发布时间】: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(以及为什么)。

【问题讨论】:

    标签: c# asp.net-mvc asp.net-web-api async-await cancellation-token


    【解决方案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 请求?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多