- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我需要为每个 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/
我是一名优秀的程序员,十分优秀!