Thread Local Storage For C# Class Library

11,257

Solution 1

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.

Solution 2

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.

Solution 3

You can achieve the same thread local storage using the [ThreadStatic] attribute or in .Net 4 by using the ThreadLocal class.

[ThreadStatic]    
private static string MyThreadGlobal;

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

There's also the CallContext class but the other approaches are probably preferred.

Share:
11,257
Jonnster
Author by

Jonnster

Updated on June 05, 2022

Comments

  • Jonnster
    Jonnster almost 2 years

    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.

  • Uwe Keim
    Uwe Keim over 12 years
    Hehe, you seem to insist on teaching us the Italian language :-)
  • L.B
    L.B over 12 years
    @xanatos The ThreadStaticAttribute can be used only on static fields is not always true. People may want to declare a per-thread-per-instance variable
  • Jonnster
    Jonnster over 12 years
    My Italian is not that great but joking apart, many thanks for the help. Although I am bit concerned about the last paragraph to do with using a ThreadPool. I don't think this will be an issue at first but it is something that might need consideration in future.
  • Jonnster
    Jonnster over 12 years
    So, am I right in saying then, in my example I would still declare a static class with a name like GlobalVar and then declare all static variables in that class with the ThreadLocal?
  • xanatos
    xanatos over 12 years
    @UweKeim I'm mortified :-( The funny thing is that I always read the MSDN pages in English :-) :-) But the MSDN loves to show me the italian version (at this time I have set it to show me the original version of pages, but it still redirects me on the it-it pages with the text in english)
  • xanatos
    xanatos over 12 years
    @L.B Taken from the MSDN page of ThreadStaticAttribute: Indicates that the value of a static field is unique for each thread.. static field
  • xanatos
    xanatos over 12 years
    @Jonnster You could use both of them if the fields are static. But ThreadStaticAttribute is (should be) faster. At this time I don't have time to benchmark it.
  • L.B
    L.B over 12 years
    @xanatos What I am saying, you can declare a field like this [ThreadStatic] object obj; which will have different instances per thread + per instance
  • xanatos
    xanatos over 12 years
    @L.B No, you can't use it on non-static fields.
  • xanatos
    xanatos over 12 years
    @Jonnster For the italian links, I have changed them to en-us links
  • xanatos
    xanatos over 12 years
    @UweKeim Have you seen other links of mine pointing at it-it resources?
  • L.B
    L.B over 12 years
    @xanatos, speaking with confidence doesn't make it true. I tried. you should have done also before commenting.
  • Uwe Keim
    Uwe Keim over 12 years
    @xanatos The funny thing is that I edited your article to point to "en-us" and you edited it back. Seems this was some concurrency issue.
  • xanatos
    xanatos over 12 years
    @L.B The fact that compiles doesn't mean that then it works. I have a train to take (not kidding). Look at this. ideone.com/8tYzl If you have queries, in 6 hours I can respond to them
  • xanatos
    xanatos over 12 years
    @L.B No problems. I had tried to write you a short example but I was in a hurry (before your last message). Today is the day I return home for the week end so I'm a little in a hurry :-) :-) (and in the end the fact that compiler compiled correctly baffled even me, then I remembered that you can't tell to an Attribute that it can attach itself only on static "things")