在控制器操作中等待异步方法后,为什么System.Web.HttpContext.Current为null?

时间:2020-10-15 14:49:39

标签: c# asp.net-mvc async-await

在我的ASP.NET MVC Web应用程序中,我的Controller操作方法之一调用了一些代码,这些代码依赖于从当前HttpContext获取信息。该代码不是我的Controller的一部分,因此不能使用Controller.HttpContext-而是使用System.Web.HttpContext.Current。 (我知道这是个坏主意,但我无法改变这一点。)

一切正常,直到我在await操作方法中添加了Controller。现在,当我随后调用使用System.Web.HttpContext.Current的代码时,它失败了,因为HttpContext.Currentnull

我阅读了一些内容,发现说System.Web.HttpContext.Current仅设置在正在处理Web请求的线程上。这就说得通了。但是,令我惊讶的是,仅使用await就足以切换到其他线程。

我的理解是,使用await不使用ConfigureAwait(false)(如var result = await myTask;)可确保使用有效的await来调用SynchronizationContext之后的代码在await之前。

我在精神上将其等同于“在同一线程上运行”-也就是说,await之后的代码将与await之前的代码在同一线程上运行(即使{{ 1}}可能正在其他线程上执行)。事实并非如此-Task前后Thread.CurrentThread.ManagedThreadId是不同的。

奇怪的是,我看到的行为与this question中描述的行为相反。

我很困惑-是否有人可以阐明(a)在进行任何await调用之后我是否应该期望System.Web.HttpContext.Current为空,以及(b)是否有任何方法可以编写代码await在同一线程上恢复后,以为空?

1 个答案:

答案 0 :(得分:0)

好的,我在类似问题上发现了this answer。显然,此行为是由ASP.NET的“怪异模式”引起的。 :-(

通过在我的web.config中添加以下内容,可以确保在同一线程上执行await之后的代码,从而使HttpContext.Current不为空。

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>