c#类库的线程本地存储
本文关键字:存储 线程 类库 | 更新日期: 2023-09-27 18:12:03
我有一个非常旧但非常大的库,我正在考虑将其转换为c#类库。现有库使用了大量存储在TLS中的全局变量。c#中没有真正的全局变量的概念但一个解决方法是使用一个静态类,比如GlobalVar把它们都放到这个类中这样就可以通过GlobalVar。xxxxxx
访问它们然而,我的想法是,这将打破所有现有的代码被转换为GlobalVar类将是一个正常的全局类,而不是每个线程存储。有没有办法让这些全局是每个线程?也就是说,c#中的__declspec (thread) static等价于什么?
在这一点上我应该补充一点,我讨厌全局变量。我认为它们通常是糟糕设计的结果。然而,由于时间限制,第一阶段是尽量少地将库转换为c#,然后第二阶段将正确地重新设计它们。有ThreadLocal类(在4.0中引入)和threadstaticatattribute。
ThreadStaticAttribute
只能用于static
字段。ThreadLocal
类可以用于"普通"字段,但速度较慢。
要注意,如果你不控制线程,你在(例如,你是一个网页的ASP。. NET和你开始一个"随机"预先使用的线程,或者你是一个线程池的线程),那么你的"线程静态"(一般来说,不是属性)变量将与前一个线程的旧值进行预初始化。(参见两个技术的例子:[ThreadStatic]属性和System.Web.HttpContext.Current.Items)
我忘记了,有线程。AllocateDataSlot,具有类似的"目标",
假设你要使用。net 4.0,你可以有一个static ThreadLocal<ThreadLocalData>
,你的ThreadLocalData
类有你所有的变量作为属性:
class ThreadLocalData
{
public int GlobalInt { get; set; }
public string GlobalString { get; set; }
}
class Global
{
static ThreadLocal<ThreadLocalData> _ThreadLocal =
new ThreadLocal<ThreadLocalData>( () => new ThreadLocalData() );
public static ThreadLocalData ThreadLocal
{
get { return _ThreadLocal.Value; }
}
}
然后像这样访问属性:
int i = Global.ThreadLocal.GlobalInt;
您可以添加任何非线程本地的全局变量作为Global
类的正常属性。
您可以使用[ThreadStatic]
属性或在。net 4中使用ThreadLocal
类来实现相同的线程本地存储。
[ThreadStatic]
private static string MyThreadGlobal;
private ThreadLocal<string> MyThreadGlobal = new ThreadLocal<string>();
也有CallContext类,但其他方法可能更受欢迎。
允许线程独占地访问自己的线程不安全版本的主要方法有三种对象。
1 - [ThreadStatic] 实现非常简单,它可以通过使用[ThreadStatic]
属性
[ThreadStatic] static int y;
现在每个线程都看到一个单独的y副本;遗憾的是,[ThreadStatic]
不能与实例字段一起工作。
2 - ThreadLocal 这是framework 4.0
的新特性,它为静态和实例字段提供线程本地存储。此外,您还可以为每个线程提供默认值,并惰性地计算该值。
static ThreadLocal<int> y = new ThreadLocal<int> (() => 10); //Static variable
ThreadLocal<int> y = new ThreadLocal<int> (() => 10); //Instance variable
3- GetData和SetData在这种方法中,使用Thread
类的两个方法:GetData
和SetData
。这些方法将数据存储在线程特定的"槽"中。类的名称Slot,所以相同的Slot可以在所有线程中使用,并且它们将获得单独的值。
// The same LocalDataStoreSlot object can be used across all threads.
LocalDataStoreSlot y= Thread.GetNamedDataSlot ("slotName");
object data = Thread.GetData (y);
Thread.SetData (y, value)