gpt4 book ai didi

c# - 跨线程的 HTTPContext

转载 作者:行者123 更新时间:2023-11-30 15:39:50 24 4
gpt4 key购买 nike

我需要为每个 Web 请求实例化一个单例对象,以便数据处理一次并在整个请求期间有效,我使用 HttpContext.Current.Items 在 HTTP 请求期间共享数据,一切都很好,直到我们需要跨多个线程的单例对象实例,我想到的第一件事是将 HttpContext 实例传递给新线程:

HttpContext context = HttpContext.Current;
ThreadPool.QueueUserWorkItem(callback =>
{
HttpContext.Current = context;
// blah blah
});

我认为这不是线程安全的方法 noted here .

使用 Reflector 我发现 HttpContext.Current.Items 实际上使用 CallContext 在每个逻辑线程中存储对象。所以我将单例接口(interface)更改为:

public static SingletonType SingletonInstance
{
get { return CallContext.GetData(key) as SingletonType; }
set { CallContext.SetData(key, value); }
}

并在启动任何新线程时简单地覆盖 SingletonInstance!代码工作正常,但似乎在重负载下不知何故,CallContext.GetData(key) 返回 null 并且应用程序崩溃并出现空引用异常!

我在想,如果 CallContext.GetData 是原子的?但这似乎不对,CallContext 是线程特定的数据存储并且必须是原子的,否则我就忽略了重点!

我的另一个猜测是设置 SingletonInstance (CallContext.SetData) 发生在一个线程中,而 CallContext.GetData 在另一个线程中执行为 noted here但我不知道如何/为什么?

更新:

我们将每个在线用户的实例保存在服务器上的一个数组中。单例对象实际上是对代表当前用户的对象的引用。当前用户必须是唯一的,并且在每个线程中都可以用于数据库查询、日志记录、错误处理等,这是如何完成的:

public static ApplicationUser CurrentUser
{
get { return CallContext.GetData("ApplicationUser") as ApplicationUser ; }
set { CallContext.SetData("ApplicationUser", value); }
}

最佳答案

如果 ASP.NET 处于负载状态,它可能会在线程之间迁移请求。一旦收到请求,页面构造函数就可以在一个线程上执行,并在另一个线程上加载页面。在这个线程开关中,CallContext 和 ThreadStatic 没有被迁移,但幸运的是 HttpContext 被迁移了。

这可能会产生误导,因为 HttpContext 是调用上下文,但这是 ASP.NET 中的一个小怪癖,可能是为了提高性能偷工减料。

您必须删除对 CallContext 的依赖并在整个过程中使用 HttpContext。

您可以在此 terrific blog post 中阅读更多详细信息由 Piers7 提供。

关于c# - 跨线程的 HTTPContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9957488/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com