“HttpContext.Current”属性和相关内容的跨线程使用

我从<Essential ASP.NET与C#>中的示例如下:

另一个需要了解的有用属性是静态电流属性
HttpContext类的。此属性始终指向当前对象
正在服务的请求的HttpContext类的实例。这
如果您正在编写将要使用的帮助器类,则可以非常方便
来自页面或其他管道类,并且可能需要访问
不管出于什么原因。通过使用静态电流属性
检索上下文时,可以避免将对它的引用传递给
助手类。例如,清单4-1中所示的类使用
用于访问查询字符串和打印的上下文的当前属性
当前响应缓冲区中的某些内容请注意,对于此静态
属性要正确初始化,调用方必须在上执行
原始请求线程,因此如果生成了其他线程
要在请求期间执行工作,必须注意提供访问权限
你自己去上下文类。

我想知道大胆部分的根本原因,一件事导致另一件事,以下是我的想法:

我们知道一个进程可以有多个线程。每个线程都有各自的堆栈。这些线程还可以访问共享内存区域堆

据我所知,堆栈是存储该线程的所有上下文的地方。线程要访问堆中的某些内容,必须使用指针,指针存储在堆栈中

因此,当我们进行一些跨线程调用时,我们必须确保所有必要的上下文信息都从调用线程的堆栈传递到被调用线程的堆栈

但我不太确定我是否犯了什么错误

如有任何意见,将不胜感激

谢谢

这里,堆栈仅限于用户堆栈

有四种因素共同作用,导致您所询问的行为:

  1. HttpContext是一个实例对象,其引用可以在HttpContext.Current
  2. Thread也是一个实例对象,其引用可以在Thread.CurrentThread
  3. Thread.CurrentThread是静态的,但在每个线程中引用不同的Thread对象
  4. HttpContext.Current实际上指向Thread.CurrentThread.ExecutionContext.IllogicalCallContext.HostContext

我们可以从以上几点得出结论:

  1. 因为HttpContext是一个实例对象,不是静态的,所以我们需要它的引用来访问它
  2. 由于HttpContext.Current实际上指向Thread.CurrentThread上的属性,因此将Thread.CurrentThread更改为其他对象可能会更改HttpContext.Current
  3. 因为Thread.CurrentThread在切换线程时会更改,HttpContext.Current在切换线程时也会更改(在本例中,HttpContext.Current变为null)

综上所述,是什么导致HttpContext.Current无法在新线程中工作?切换线程时发生的Thread.CurrentThread引用更改会更改HttpContext.Current引用,从而阻止我们访问所需的HttpContext实例

重申一下,这里唯一神奇的事情是Thread.CurrentThread在每个线程中引用不同的对象。HttpContext与任何其他实例对象一样工作。由于同一AppDomain中的线程可以引用相同的对象,所以我们所要做的就是将HttpContext的引用传递给我们的新线程。没有要加载的上下文信息或类似信息。(将HttpContext传递给其他线程有一些相当严重的潜在问题,但没有什么可以阻止您这样做)

在研究过程中,我遇到了一些最后的旁注:

  1. 在某些情况下,线程的ExecutionContext从一个线程“流动”(复制)到另一个线程。那么,为什么HttpContext没有“流”到我们的新线程?因为HttpContext没有实现iLogicThreadAffinative接口。存储在ExecutionContext中的类只有在实现iLogicThreadAffinative时才流动

  2. 如果不流动,ASP.NET如何将HttpContext从一个线程移动到另一个线程(线程敏捷性)?我不完全确定,但它可能会在HttpApplication.OnThreadEnter()中传递它

发表评论