HttpContext.RequestAborted和CancellationToken参数之间有什么区别? [英] What's the difference between HttpContext.RequestAborted and CancellationToken parameter?

查看:501
本文介绍了HttpContext.RequestAborted和CancellationToken参数之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为 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);
    }
}

选项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 (看起来像个错误).在这两种情况下,令牌都已填充(可能是因为struct?)

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

解决方案

我知道这是一个2个月大的问题,但今天我也一直在为此而苦苦挣扎,并得出了一些结论.


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

根据此线程,这些都是完全相同的事情.来自 Cancellation来源:

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

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

HttpContext.RequestAborted的优点在于,它可以在所有控制器的方法中使用,而不仅仅是操作. CancellationToken参数易于恕我直言,但如果您有许多嵌套方法需要对令牌做出反应,则通过其参数传播令牌可能不切实际.我只会使用一种更适合您需求的产品.


在同一线程中,另一则帖子:

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

我知道,这不是您的情况,而是我的.


最后,仍然来自同一话题,尤其是讨论问题(特别是在与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.它使用IIS Express来启动该应用程序(包括Kestrel).发出请求并在7秒钟之前中止它(通过关闭浏览器选项卡).断点触发时,cancelToken.IsCancellationRequestedfalse.

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

一切正常.

我也曾尝试使用ASP .NET Core 1.1进行同样的尝试,但没有成功.


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

I'm trying to create an async view component for ASP.NET Core 2.0. It will do an action that should be cancelled when the user navigates away from the page. I've got the following options:

  1. Using the HttpContext.RequestAborted
  2. Using a CancellationToken parameter
  3. I could also chain the tokens

Option 1 looks like this:

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

Option 2 looks like this:

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

Both action do not work with Kestrel (looks like a bug). In both cases the tokens are filled (maybe because of struct?)

What is the difference and what should I use?

解决方案

I know this is a 2 months old issue, but I have been struggling with this today too and came to some conclusions.


What is the difference and what should I use?

According to this thread these are exactly the same things. From CancellationTokenModelBinder source:

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

I can confirm, I always get the same values from HttpContext.RequestAborted and CancellationToken injection.

Advantage of HttpContext.RequestAborted is that it is available in all controller's methods, not just actions. The CancellationToken parameter is IMHO better readable but if you have a number of nested methods that need to react to the token, it may become impractical to propagate it through their parameters. I would just use the one that better suits your needs.


From the same thread, another post:

This only works in 2.0 not in 1.x

I know, this is not your case but it was mine.


Finally, still from the same thread and especially discussion here, there's a problem in IIS (specifically in its interface with Kestrel). AFAIK you have to use Kestrel and optionally (mandatory for 1.x) a reverse proxy such as IIS, Apache or Nginx. I believe this is your case.


Some quick testing: I created a project from Web API template using ASP .NET Core 2.0 and modified the first action in the controller it created:

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

Hit F5. It starts the app (including Kestrel) with IIS Express in front of it. Make the request and abort it (by closing a browser tab) before the 7 seconds. cancelToken.IsCancellationRequested is false when the breakpoint triggers.

Now, change the debug profile from IIS Express to WebApplication1 (or whatever it is called):

Everything works as expected for me.

I did also try the same with ASP .NET Core 1.1 but with no success.


AFAIK with ASP .NET Core 2.0, one should be able to use Kestrel on its own. I don't know if Apache or Nginx are doing better than IIS.

这篇关于HttpContext.RequestAborted和CancellationToken参数之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆