23

请考虑以下 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保证存在?

  1. 我知道,HttpContext.Current由于我完全同意的原因,这些天来,更广泛的社区经常不赞成使用……我只是在帮助某人摆脱困境。

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

非常感谢

4

2 回答 2

27

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

那是对的。但是,让我们先谈谈asyncASP.NET。

async需要 .NET 4.5。此外,ASP.NET 4.5 在服务器端引入了“怪癖模式”,您必须关闭SynchronizationContext怪癖。您可以通过设置使用带有值的来做到这一点。httpRuntime.targetFramework4.5 appSettingsaspnet:UseTaskFriendlySynchronizationContexttrue

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

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

跨点AspNetSynchronizationContext保留当前请求上下文。await这包括HttpContext.Current(其中包括ItemsUser等)。

另一种可能性是,它也跨点CallContext.Logical[Get|Set]Data流动。await如果您不希望代码依赖于 ,这很有用HttpContext,但开销稍大。

几周前,我在 ThatConference 上做了一个async关于服务器端的演讲;您可能会发现这些幻灯片很有帮助,尤其是那些处理上下文和线程本地状态的幻灯片。

于 2013-08-27T12:29:25.350 回答
6

长话短说,它通常应该。除非您使用ConfigureAwait(false)which 可能会产生副作用,即继续不流动上下文。

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

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

更新

笔记!!最初我把假的。但它必须是真实的,这样上下文才能流动。

于 2013-08-27T09:00:51.960 回答