c#类库的线程本地存储

本文关键字:存储 线程 类库 | 更新日期: 2023-09-27 18:12:03

我有一个非常旧但非常大的库,我正在考虑将其转换为c#类库。现有库使用了大量存储在TLS中的全局变量。c#中没有真正的全局变量的概念但一个解决方法是使用一个静态类,比如GlobalVar把它们都放到这个类中这样就可以通过GlobalVar。xxxxxx

访问它们

然而,我的想法是,这将打破所有现有的代码被转换为GlobalVar类将是一个正常的全局类,而不是每个线程存储。有没有办法让这些全局是每个线程?也就是说,c#中的__declspec (thread) static等价于什么?

在这一点上我应该补充一点,我讨厌全局变量。我认为它们通常是糟糕设计的结果。然而,由于时间限制,第一阶段是尽量少地将库转换为c#,然后第二阶段将正确地重新设计它们。

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类的两个方法:GetDataSetData。这些方法将数据存储在线程特定的"槽"中。类的名称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)