HttpContext.RequestAborted 和 CancellationToken 参数有什么区别?

Kee*_*ker 9 asp.net-mvc kestrel .net-core asp.net-core-viewcomponent

我正在尝试为ASP.NET Core 2.0创建异步视图组件。当用户离开页面时,它会执行一个应该被取消的操作。我有以下选择:

  1. 使用 HttpContext.RequestAborted
  2. 使用 CancellationToken 参数
  3. 我也可以链接令牌

选项 1 如下所示:

public class AmazingMessageViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync(string text, int wait)
    {
        //uses request aborted
        await Task.Delay(wait, HttpContext.RequestAborted);
        return View<string>(text);
    }
}
Run Code Online (Sandbox Code Playgroud)

选项 2 如下所示:

public class AmazingMessageViewComponent : ViewComponent
{
    public async Task<IViewComponentResult> InvokeAsync(CancellationToken cancellationToken, string text, int wait)
    {
        await Task.Delay(wait, cancellationToken);
        return View<string>(text);
    }
}
Run Code Online (Sandbox Code Playgroud)

这两个操作都不适用于 Kestrel(看起来像一个错误)。在这两种情况下,都填充了令牌(可能是因为结构?)

有什么区别,我应该使用什么?

Luk*_* Z. 8

我知道这是一个 2 个月前的问题,但我今天也一直在努力解决这个问题并得出了一些结论。


有什么区别,我应该使用什么?

根据这个线程,这些是完全相同的东西。从CancellationTokenModelBinder 来源

var model = (object)bindingContext.HttpContext.RequestAborted;
Run Code Online (Sandbox Code Playgroud)

我可以确认,我总是从HttpContext.RequestAbortedCancellationToken注入中获得相同的值。

优点HttpContext.RequestAborted是它在所有控制器的方法中都可用,而不仅仅是动作。CancellationToken恕我直言,该参数可读性更好,但如果您有许多嵌套方法需要对令牌做出反应,则通过它们的参数传播它可能变得不切实际。我只会使用更适合您需求的那种。


来自同一线程,另一篇文章

这仅适用于 2.0 而不适用于 1.x

我知道,这不是你的情况,而是我的情况。


最后,仍然来自同一个线程,尤其是这里的讨论,IIS 中存在一个问题(特别是它与 Kestrel 的接口)。AFAIK 你必须使用 Kestrel 和可选的(对于 1.x 是强制性的)反向代理,如 IIS、Apache 或 Nginx。我相信这是你的情况。


一些快速测试:我使用 ASP .NET Core 2.0 从 Web API 模板创建了一个项目,并修改了它创建的控制器中的第一个操作:

// GET api/values
[HttpGet]
public IEnumerable<string> Get(CancellationToken cancelToken)
{
    Thread.Sleep(7000);
    cancelToken.ThrowIfCancellationRequested(); // breakpoint here
    return new string[] { "value1", "value2" };
}
Run Code Online (Sandbox Code Playgroud)

按F5。它启动应用程序(包括 Kestrel),并在其前面显示 IIS Express。发出请求并在 7 秒之前中止它(通过关闭浏览器选项卡)。cancelToken.IsCancellationRequestedfalse断点触发的时间。

现在,将调试配置文件从 IIS Express 更改为 WebApplication1(或任何名称):

在此处输入图片说明

一切都按我的预期工作。

我也对 ASP .NET Core 1.1 进行了同样的尝试,但没有成功。


AFAIK 与 ASP .NET Core 2.0,应该能够单独使用 Kestrel。我不知道 Apache 或 Nginx 是否比 IIS 做得更好。