Why HttpContext.Current is not null in async/await with ConfigureAwait

荒凉一梦 提交于 2021-02-08 03:39:55

问题


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

回答1:


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

It is rewritten to:

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

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

This is rewritten too:

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

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.



来源:https://stackoverflow.com/questions/55080787/why-httpcontext-current-is-not-null-in-async-await-with-configureawait

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!