HttpContext.RequestAborted和CancellationToken参数之间的区别是什么?

时间:2017-11-07 08:50:48

标签: asp.net-mvc .net-core kestrel asp.net-core-viewcomponent

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

  1. 使用HttpContext.RequestAborted
  2. 使用CancellationToken参数
  3. 我也可以链接令牌
  4. 选项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);
        }
    }
    

    选项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);
        }
    }
    

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

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

1 个答案:

答案 0 :(得分:2)

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

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

根据this thread,这些是完全相同的。来自CancellationTokenModelBinder source

var model = (object)bindingContext.HttpContext.RequestAborted;

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

HttpContext.RequestAborted的优势在于它可用于所有控制器的方法,而不仅仅是操作。 CancellationToken参数是IMHO更好的可读性,但如果您有许多需要对令牌作出反应的嵌套方法,则通过它们的参数传播它可能变得不切实际。我会使用最适合您需求的那个。

来自同一个帖子,another post

  

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

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

最后,仍然来自同一个主题,特别是讨论here,有problem in 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" };
}

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

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

enter image description here

一切都像我预期的那样有效。

我也尝试使用ASP .NET Core 1.1,但没有成功。

使用ASP .NET Core 2.0的AFAIK,应该可以自己使用Kestrel。我不知道Apache或Nginx是否比IIS做得更好。