HttpContext.Current通过Thread获取当前上下文(我直接查看了实现)。
更正确的说法是HttpContext
应用于线程;或者一个线程“进入”HttpContext
.
在异步任务中使用 HttpContext.Current 是不可能的,因为它可以在另一个线程上运行。
一点也不;的默认行为async
/await
将在任意线程上恢复,但该线程将在恢复之前进入请求上下文async
method.
这其中的关键是SynchronizationContext
。我有一个关于该主题的 MSDN 文章如果你不熟悉它。 ASynchronizationContext
为平台定义“上下文”,常见的是 UI 上下文(WPF、WinPhone、WinForms 等)、线程池上下文和 ASP.NET 请求上下文。
ASP.NET 请求上下文管理HttpContext.Current
以及其他一些事情,例如文化和安全。 UI 上下文都与单个线程紧密关联(theUI 线程),但 ASP.NET 请求上下文不绑定到特定线程。然而,它只允许请求上下文中有一个线程一次.
解决方案的另一部分是如何async
and await
工作。我有一个async我的博客上有介绍,描述了他们的行为。总之,await
默认情况下将捕获当前上下文(即SynchronizationContext.Current
除非是null
),并使用该上下文来恢复async
方法。所以,await
自动捕获 ASP.NETSynchronizationContext
并将恢复async
该请求上下文中的方法(从而保留文化、安全性和HttpContext.Current
).
If you await
ConfigureAwait(false)
,那么你明确地告诉await
to not捕捉上下文。
请注意,ASP.NET 确实必须更改其SynchronizationContext
干净利落地工作async
/await
。您必须确保应用程序是针对 .NET 4.5 编译的,并且还在其 web.config 中明确针对 4.5;这是新 ASP.NET 4.5 项目的默认设置,但如果您从 ASP.NET 4.0 或更早版本升级现有项目,则必须显式设置。
您可以通过针对 .NET 4.5 执行应用程序并观察来确保这些设置正确SynchronizationContext.Current
。如果是AspNetSynchronizationContext
,那你就很好了;如果它是LegacyAspNetSynchronizationContext
,那么设置是错误的。
只要设置正确(并且您使用的是 ASP.NET 4.5AspNetSynchronizationContext
),然后你就可以安全地使用HttpContext.Current
后await
不用担心。