TLS(线程局部存储,thread local storage)在类库和多线程应用开发中是个有用的东东,在很多语言和工具中都有很好的支持(如Visual C++里面的__declspec(thread)Delphi中的threadvar等等,Win32 API中也有对应的Tls族函数)。有些刚接触.NET的朋友就开始抱怨了,说在管制环境下没有TLS了,得自己写了。其实不然,虽然在C#/VB.NET等语言中没有直接的关键字或语句来声明TLS,但是CLR通过定制属性更直观的支持着这一特性,这个属性就是ThreadStaticAttribute

 

  如果你希望一个静态成员(static in C#, Shared in VB.NET)对于不同的线程(更准确的说,app-domain与线程的组合)有不同的值(也即TLS的行为),则只需要为其设置ThreadStatic属性就可以了,无需作任何编程处理(当然这是declarative的做法,相应的programmatic方法也有,具体的可以参见Thread.AllocateDataSlotThread.AllocateNamedDataSlot方法,或检索.NET SDK Documentation Index中的TLS条目)。

 

  文档中提醒一点要注意的是,任何访问线程局部静态成员的代码,只要不是运行在访问该成员所在类的第一个线程上时,都应该将该成员看作是null引用(引用类型)或默认初始值(值类型)。也就是说,不要依赖于类的构造器去初始化ThreadStatic成员,原因是显而易见的。

 

  另外,在ASP.NET等多线程环境中使用TLS成员也要慎重,因为这些线程的生命周期不是由你来控制的,它们是从HttpRuntime管理的线程池中被重用的,因此在一次请求中使用的TLS成员有可能在另一次毫不相关的请求中被得到或修改(除非这就是你希望的效果)。如果希望使用请求相关的存储环境,可以考虑使用HttpContext.Current实例的Items集合(该集合在Server.Transfer等情况下可用于在同一次请求的不同页面间传递和共享状态)。