异步操作后的 HttpContext.Current.Items
Posted
技术标签:
【中文标题】异步操作后的 HttpContext.Current.Items【英文标题】:HttpContext.Current.Items after an Async operation 【发布时间】:2013-08-29 20:59:39 【问题描述】:考虑以下 ASP.NET Web API 委托处理程序:
public class MyHandler : DelegatingHandler
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
var guid = Guid.NewGuid();
HttpContext.Current.Items["foo"] = guid;
// An Async operation
var result = await base.SendAsync(request, cancellationToken);
//All code from this point is not gauranteed to run on the same thread that started the handler
var restoredGuid = (Guid)HttpContext.Current.Items["foo"];
//Is this gauranteed to be true
var areTheSame = guid == restoredGuid;
return result;
上面的例子是在一个委托处理程序中,我试图解决的同样的问题也适用于控制器、业务对象等。
我最终试图在每个 HTTP 请求的各种对象之间提供一些简单的内存共享状态
据我了解,在异步操作期间,最初运行该操作的 ASP.NET 线程将返回到线程池,并且可以在异步操作完成后使用不同的线程来完成请求。
这会影响HttpContext.Current.Items
集合吗?
当请求恢复时,Items
集合中的项目是否保证存在?
我知道使用 HttpContext.Current
经常被
由于我完全同意的原因,这些天来更广泛的社区
与...我只是在帮助某人摆脱困境。
将此数据存储在 Request.Items
集合中不适合解决此问题,因为我的同事由于一些糟糕的设计决策需要静态。
非常感谢
【问题讨论】:
这可能会有所帮助:***.com/questions/17261571/… 还有这个:***.com/questions/15196556/… 嗨,杰森,这些问题;虽然相似;不完全一样。不过还是谢谢。 啊,好吧 :) 不用担心。HttpContext
将被保留,但延续线程可能不一样。 AspNetSynchronizationContext 将管理上下文。
【参考方案1】:
据我了解,在异步操作期间,最初运行该操作的 ASP.NET 线程将返回到线程池,并且可以在异步操作完成后使用不同的线程来完成请求。
没错。但是,让我们花一分钟来谈谈 ASP.NET 上的async
。
async
需要 .NET 4.5。此外,ASP.NET 4.5 在服务器端引入了“怪癖模式”,您必须关闭SynchronizationContext
怪癖关闭。您可以通过将httpRuntime.targetFramework
设置为4.5
或 使用appSettings
和aspnet:UseTaskFriendlySynchronizationContext
值为true
来做到这一点。
如果您的 web.config 没有这些条目之一,则 async
的行为未定义。有关详细信息,请参阅this post。我建议使用targetFramework
设置并修复出现的任何问题。
这会影响 HttpContext.Current.Items 集合吗?当请求恢复时,是否保证存在 Items 集合中的项目?
AspNetSynchronizationContext
跨await
点保留当前请求上下文。这包括HttpContext.Current
(包括Items
、User
等)。
另一种可能性是CallContext.Logical[Get|Set]Data
,它也流经await
点。如果您不希望代码依赖于 HttpContext
,这很有用,但开销会稍高。
几周前,我在 ThatConference 上发表了演讲 async
on the server side;您可能会发现这些幻灯片很有帮助,尤其是那些处理上下文和线程本地状态的幻灯片。
【讨论】:
谢谢斯蒂芬,很好的回应。【参考方案2】:长话短说,通常应该。除非您使用ConfigureAwait(false)
,否则可能会产生副作用,即继续不流动上下文。
或者尝试在您的应用中添加此设置。
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
更新
注意!! 最初我把假的。但它必须是true,这样上下文才能流动。
【讨论】:
以上是关于异步操作后的 HttpContext.Current.Items的主要内容,如果未能解决你的问题,请参考以下文章