为什么HttpContext.Current在带有ConfigureAwait的异步/等待中不为null [英] Why HttpContext.Current is not null in async/await with ConfigureAwait

查看:55
本文介绍了为什么HttpContext.Current在带有ConfigureAwait的异步/等待中不为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个从控制器调用的库异步函数.我期望HttpContext.Current在所有地方都使用ConfigureAwait(false)等待后为null,但在控制器中不为null.有人可以解释为什么吗?

I have a library async function called from controller. I expected HttpContext.Current to be null after await with ConfigureAwait(false) everywhere, but in controller it is not null. Can somebody explain why?

//in libraby
public class MyClass
{
    public async Task WaitAsync()
    {
        await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

        var httpContext = System.Web.HttpContext.Current; // null, OK
    }
}

public class HomeController : Controller
{
    public async Task<ActionResult> Index()
    {
        var class1 = new MyClass();
        await class1.WaitAsync();

        var httpContext = System.Web.HttpContext.Current; // not null, WHY???

        return View("Index");
    }
}

推荐答案

尽管比这复杂得多,但是您可以将 await 想象成一种 ContinueWith .因此,如果您编写例如:

Though it is much more complex than that, you can picture await as a kind of ContinueWith. So if you write for instance:

DoSomeStuff();
await WaitAsync()
DoMoreStuff();

它被重写为:

DoSomeStuff();
WaitAsync().ContinueWith(_ => DoMoreStuff());

.ConfigureAwait 设置继续执行的上下文.使用 ConfigureAwait(true)(默认设置),延续将在与调用者相同的上下文中执行.使用 ConfigureAwait(false),延续将在线程池的默认不变上下文中执行.通过前面的简化,让我们想象将 ConfigureAwait(true)重写为 ContinueWithSameContext ,将 ConfigureAwait(false)重写为 ContinueWithThreadPool >.

.ConfigureAwait sets the context in which the continuation will execute. With ConfigureAwait(true) (the default), the continuation will execute in the same context as the caller. With ConfigureAwait(false), the continuation will execute in the default invariant context, on the threadpool. With our previous simplification, let's imagine ConfigureAwait(true) will be rewritten to ContinueWithSameContext and ConfigureAwait(false) to ContinueWithThreadPool.

现在,如果我们有嵌套方法,会发生什么?例如,您的代码:

Now what happens if we have nested methods? For instance, your code:

public async Task WaitAsync()
{
    await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false);

    var httpContext = System.Web.HttpContext.Current; // null, OK
}

public async Task<ActionResult> Index()
{
    var class1 = new MyClass();
    await class1.WaitAsync();

    var httpContext = System.Web.HttpContext.Current; // not null, WHY???

    return View("Index");
}

这也被重写:

public Task WaitAsync()
{
    return Task.Delay(TimeSpan.FromSeconds(1))
        .ContinueWithThreadPool(_ => 
        {
            var httpContext = System.Web.HttpContext.Current; // null, OK
        });
}        

public Task<ActionResult> Index()
{
    var class1 = new MyClass();
    return class1.WaitAsync().ContinueWithSameContext(_ =>
    {
        var httpContext = System.Web.HttpContext.Current; // not null, WHY???

        return View("Index");
    }
}

以这种方式重写,您会看到 WaitAsync 的延续将在与 Task< ActionResult>Index(),解释为什么HttpContext不为空.

Rewritten this way, you see that the continuation of WaitAsync will run on the same context as Task<ActionResult> Index(), explaining why the HttpContext isn't null.

这篇关于为什么HttpContext.Current在带有ConfigureAwait的异步/等待中不为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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