C#类库的线程本地存储
我有一个非常古老但非常大的库,我正在考虑转换为C#类库。 现有库使用存储在TLS中的许多全局变量。 C#没有真正的全局变量概念,但一种解决方法是使用一个名为GlobalVar的静态类,并将它们全部放在这个类中,以便可以通过GlobalVar.xxxxxx访问它们
但是,我的想法是,这会破坏所有正在转换的现有代码,因为GlobalVar类将是一个普通的全局类而不是每个线程存储。 有没有办法让每个线程的这些全局变量? 即C#中__declspec(thread)静态的等价物是什么?
我应该补充一点,我讨厌全局变量。 我认为它们往往是设计不佳的结果。 但是,由于严格的时间限制,第一阶段是将库转换为C#,最小化,然后第2阶段将重新设计它们。
有ThreadLocal类(在4.0中引入)和ThreadStaticAttribute 。
ThreadStaticAttribute
只能用于static
字段。 ThreadLocal
类可以在“普通”字段上使用,但速度较慢。
请注意,如果你不控制你所在的线程(例如你是一个ASP.NET页面,你开始使用“随机”预先使用的线程,或者你是一个ThreadPool的线程),那么你的“thread-static”(通常不是属性)变量将使用前一个线程的旧值进行预初始化。 (参见例如两种技术的故事:[ThreadStatic]属性和System.Web.HttpContext.Current.Items )
我忘记了,有一些Thread.AllocateDataSlot具有与其他类似的“目标”。
您可以使用[ThreadStatic]
属性实现相同的线程本地存储,或使用ThreadLocal
类在.Net 4中实现。
[ThreadStatic] private static string MyThreadGlobal; private ThreadLocal MyThreadGlobal = new ThreadLocal ();
还有CallContext类,但其他方法可能更受欢迎 。
假设您将使用.NET 4.0,您可以拥有一个static ThreadLocal
,其中您的ThreadLocalData
类将所有变量作为属性:
class ThreadLocalData { public int GlobalInt { get; set; } public string GlobalString { get; set; } } class Global { static ThreadLocal _ThreadLocal = new ThreadLocal ( () => new ThreadLocalData() ); public static ThreadLocalData ThreadLocal { get { return _ThreadLocal.Value; } } }
然后,您将访问如下属性:
int i = Global.ThreadLocal.GlobalInt;
您可以添加任何非线程局部的全局变量作为Global
类的常规属性。