异步操作后的HttpContext.Current.Items

Gav*_*orn 22 c# asp.net async-await .net-4.5 asp.net-web-api

请考虑以下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;
    }
}
Run Code Online (Sandbox Code Playgroud)

以上示例位于委托处理程序中,我尝试修复的同一问题适用于控制器,Business Objects等.

我最终试图在每个HTTP请求的各种对象之间提供一些简单的内存中共享状态

据我所知,在异步操作期间,最初运行操作的ASP.NET线程返回到线程池,并且在异步操作完成后可以使用不同的线程来完成请求.

这会影响HttpContext.Current.Items收藏吗?Items请求恢复后,集合中的项目是否保证在那里?

  1. 我知道HttpContext.Current这些日子里,由于我完全同意的原因,使用这种情况经常不受欢迎......我只是帮助某人摆脱困境.

  2. 将这些数据存储在Request.Items集合中并不适合解决这个问题,因为我的同事由于一些糟糕的设计决策而需要静态.

非常感谢

Ste*_*ary 26

据我所知,在异步操作期间,最初运行操作的ASP.NET线程返回到线程池,并且在异步操作完成后可以使用不同的线程来完成请求.

那是正确的.但是让我们谈谈asyncASP.NET只需一分钟.

async需要.NET 4.5.此外,ASP.NET 4.5引入了在服务器侧的"怪癖模式",你必须打开SynchronizationContext怪癖关闭.您可以通过设置httpRuntime.targetFramework4.5 使用appSettingswith aspnet:UseTaskFriendlySynchronizationContext值来实现此目的true.

如果您的web.config没有其中一个条目,那么行为async是未定义的.有关详细信息,请参阅此帖子.我建议使用targetFramework设置并修复出现的任何问题.

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

AspNetSynchronizationContext保持跨越当前请求上下文await点.这包括HttpContext.Current(其包括Items,User等).

另一种可能性是CallContext.Logical[Get|Set]Data,它也流过各await点.如果您不希望代码依赖HttpContext,但稍微增加开销,这将非常有用.

几周前,我async在服务器端的 ThatConference上发表了演讲.您可能会发现幻灯片很有用,特别是那些处理Context和Thread-Local State的幻灯片.


Ali*_*tad 5

长话短说,通常应该.除非您正在使用ConfigureAwait(false),否则会产生副作用,并且不会继续上下文.

或者尝试在您的应用中添加此设置.

<appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
Run Code Online (Sandbox Code Playgroud)

UPDATE

注意!!最初我把假.但它必须是真实的,以便上下文流动.