Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread Local Storage For C# Class Library

I have a very old but very large library which I am considering converting to a C# class library. The existing library uses a lot of global variables stored in the TLS. C# has no real concept of global variables but one workaround is to use a static class called something like GlobalVar and put them all in this class so they can be accessed via GlobalVar.xxxxxx

However, my thinking is that this will break all the existing code which is being converted as the GlobalVar class will be a normal global class and not per thread storage. Is there a way of getting these globals to be per thread? i.e. what is the equivalent of __declspec (thread) static in C#?

I should add at this point that I hate global variables. I think they are often the result of poor design. However, due to tight time restrictions, phase one is to convert the library to C# with minimum fuss and then phase 2 will be to redesign them properly.

like image 803
Jonnster Avatar asked Oct 21 '11 14:10

Jonnster


2 Answers

There are the ThreadLocal class (introduced in 4.0) and the ThreadStaticAttribute.

The ThreadStaticAttribute can be used only on static fields. The ThreadLocal class can be used on "normal" fields but it is slower.

Be aware that if you don't control the thread you are on (for example you are a page of ASP.NET and you start on a "random" pre-used thread, or you are a thread of a ThreadPool), then your "thread-static" (in general, not the attribute) variables will be pre-initialized with the old values of the previous thread. (see for example A tale of two techniques: The [ThreadStatic] Attribute and System.Web.HttpContext.Current.Items)

I was forgetting, there is the Thread.AllocateDataSlot that has similar "objectives" than the others.

like image 88
xanatos Avatar answered Sep 20 '22 06:09

xanatos


Presuming you're going to use .NET 4.0, you could have a static ThreadLocal<ThreadLocalData> where your ThreadLocalData class has all your variables as properties:

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; }
    }
}

You would then access the properties like this:

int i = Global.ThreadLocal.GlobalInt;

You could add any global variables that are not thread-local as normal properties of the Global class.

like image 37
Nick Butler Avatar answered Sep 18 '22 06:09

Nick Butler