ThreadStaticAttribute 的作用是告诉CLR,它标记的静态字段的存取是依赖当前线程,而独立于其他线程的。

例如:

class MyClass{
    [ThreadStatic] static public string threadvalue;
}

MyClass 中的threadvalue就是一个线程静态字段 。 如果一个程序中同时有多个线程同时访问这个字段,则每个线程访问的都是独立的threadvalue 。例如线程1设置它为”hello”,然后线程2设置它为”world”,最后线程1读取它的时候,得到的是”hello”。

基于这个,线程静态字段有以下特征:

  • 它是静态的字段。所以不需要MyClass的实例,直接用 MyClass.threadvalue的形式来访问就可以了。
  • 它的存取是根据线程来指定内存位置的,所以它的存取速度较慢。
  • 访问线程静态字段不可能发生线程不同步问题。因为虽然语意上不同线程访问的是同一字段,但实际上不同线程访问的是不同的内存块。
  • 一条线程不可能访问到另外一条线程上的线程静态字段。就算你得到另外一条线程的System.Threading.Thread 对象的引用也不行。

但是,使用线程静态字段要注意:

  • 字段上的初始化语句在类的静态构造方法中执行。所以语句只执行一句。其他线程再访问这个字段时,为字段的类型的默认值。
  • 如果不同线程上的字段都引用同一对象,那么不代表该对象是线程同步的。因为[ThreadStatic]指的是字段是隔离的。但是它引用的对象则不被[ThreadStatic]控制。

如果你知道 System.Runtime.Remoting.Messaging.Context (以下简称MContext)
那么MContext和线程静态字段有什么不同呢?

  • 他们可以说都是与当前线程相关的。但是他们不是同一个东西。
  • MContext是基于名称的,可以根据名称储存不同的数据。而ThreadStatic不会有名称冲突。
  • ThreadStatic 是CLR内部实现的。而 MContext 是附属在 System.Threading.Thread 对象的一个字典。
  • 线程静态字段的存取速度比MContext的快
  • MContext被叫做逻辑线程上下文数据。它的数据会在异步调用的时候复制到另外一条线程中。而线程静态字段是不会被复制的。(例如 eventHandlerInst.BeginInvoke(...)时,在新的线程中,就拥有原线程上MContext的数据。在eventHandlerInst.EndInvoke执行时,新线程上的MContext上的数据就会还原到调用EndInvoke的线程上.这个在以后讲到Remoting时会详细说)
  • System.Web.HttpContext.Current 是用 MContext 实现的。

[ThreadStatic]的一些应用的例子?

  • 你可能需要模仿HttpContext,弄个MyClass.Current , 或者根据Singleton模式,弄个ThreadSingleton .
  • 你可能会有工作线程。你以往是通过线程上传递一个对象用于共享数据的。这样所有的对象啊,方法啊都变得怪怪的。现在你可以把这些数据直接以[ThreadStatic]的形式存取了。
  • 你可能需要弄个这样的类:

    (天啊。FreeTextBox把我的\t扔了)

目前就说到这里吧。欢迎补充。