Локальное Хранилище Потоков Для Библиотеки Классов C#

У меня есть очень старая, но очень большая библиотека, которую я рассматриваю возможность преобразования в библиотеку классов C#. Существующая библиотека использует множество глобальных переменных, хранящихся в TLS. C# не имеет реальной концепции глобальных переменных, но один обходной путь-использовать статический класс, называемый чем-то вроде GlobalVar, и поместить их все в этот класс, чтобы к ним можно было получить доступ через GlobalVar.xxxxxx

однако я думаю, что это нарушит весь существующий код, который преобразуется как Класс GlobalVar будет обычным глобальным классом, а не хранилищем потоков. Есть ли способ заставить эти глобалы быть в потоке? т. е. Что такое эквивалент _ _ declspec (thread) static в C#?

Я должен добавить, что я ненавижу глобальные переменные. Я думаю, что они часто являются результатом плохого дизайна. Однако из-за жестких ограничений по времени Фаза 1 должна преобразовать библиотеку в C# с минимальной суетой, а затем фаза 2 будет правильно их перепроектировать.

3 ответов


есть ThreadLocal класса (введен в 4.0) и ThreadStaticAttribute.

на ThreadStaticAttribute можно использовать только на static поля. The ThreadLocal класс можно использовать в "нормальных" полях, но он медленнее.

имейте в виду, что если вы не контролируете поток, в котором находитесь (например, вы являетесь страницей ASP.NET и вы начинаете с" случайного "предварительно используемого потока, или вы являетесь потоком ThreadPool), затем ваш" поток-статический " (в общем, не атрибут) переменные будут инициализированы со старыми значениями предыдущего потока. (см., например,рассказ о двух техниках: [ThreadStatic] атрибут и система.Сеть.Свойство HttpContext.Текущий.Предметы)

Я забыл, есть нить.AllocateDataSlot это имеет аналогичные "цели", чем другие.


вы можете достичь того же локального хранилища потоков, используя [ThreadStatic] атрибут или в .Net 4 с помощью ThreadLocal класса.

[ThreadStatic]    
private static string MyThreadGlobal;

private ThreadLocal<string> MyThreadGlobal = new ThreadLocal<string>();

есть еще CallContext class но другие подходы, вероятно, предпочтительнее.


предполагая, что вы собираетесь использовать .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 класса.