异步操作后的 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 使用appSettingsaspnet:UseTaskFriendlySynchronizationContext 值为true 来做到这一点。

如果您的 web.config 没有这些条目之一,则 async 的行为未定义。有关详细信息,请参阅this post。我建议使用targetFramework 设置并修复出现的任何问题。

这会影响 HttpContext.Current.Items 集合吗?当请求恢复时,是否保证存在 Items 集合中的项目?

AspNetSynchronizationContextawait 点保留当前请求上下文。这包括HttpContext.Current(包括ItemsUser 等)。

另一种可能性是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的主要内容,如果未能解决你的问题,请参考以下文章

获取客户端IP和归属地

C#获取cookie值

异步操作后的 HttpContext.Current.Items

es6 Promise

走进异步编程的世界之GUI 中执行异步操作

回调与Promise