Setting a global variable in a thread - C#

23,708

Solution 1

One solution would be to use a public static field, with the ThreadStatic attribute:

[ThreadStatic]
public static int ThreadSpecificStaticValue;

A static field marked with ThreadStaticAttribute is not shared between threads. Each executing thread has a separate instance of the field, and independently sets and gets values for that field. If the field is accessed on a different thread, it will contain a different value.

Solution 2

You could use the built in storage mechanism of the thread class:

public class Program
{
  private static LocalDataStoreSlot _Slot = Thread.AllocateNamedDataSlot("webserver.data");

  public static void Main(string[] args)
  {
    var threads = new List<Thread>();

    for (int i = 0; i < 5; i++)
    {
      var thread = new Thread(DoWork);
      threads.Add(thread);
      thread.Start(i);
    }

    foreach (var thread in threads) thread.Join();
  }

  private static void DoWork(object data)
  {
    // initially set the context of the thread
    Thread.SetData(_Slot, data);

    // somewhere else, access the context again
    Console.WriteLine("Thread ID {0}: {1}", Thread.CurrentThread.ManagedThreadId, Thread.GetData(_Slot));
  }

}

Sample output:

enter image description here

That'll work with threads spawned by the thread pool as well.

Share:
23,708

Related videos on Youtube

Arlen Beiler
Author by

Arlen Beiler

I like programming, astronomy, history, language, and music. Come unto me, all ye that labor and are heavy laden, and I will give you rest. Take my yoke upon you and learn of me for I am meek and lowly in heart and ye shall find rest unto your soul. For my yoke is easy and my burden is light.

Updated on March 15, 2020

Comments

  • Arlen Beiler
    Arlen Beiler about 4 years

    I have an HTTP server that I am writing using HTTP listener, and I would like to somehow declare certain variables as accessible from anywhere within a thread.

    • My webserver class is instanced based, so I can't really use a static variable.
    • I could use an instance variable as all of the code is in one class, but...I don't know.

    I thought of using a dictionary: Dictionary</*[type of Thread ID here]*/,ThreadData>, but I'm concerned there might be threading issues. ThreadData would probably be a class instance, but I might use a struct, depending on which would be more efficient.

    • If I would key the dictionary to the Thread IDs and program it so that one thread would only ask for its own entry in the dictionary, would there be any thread-related problems when accessing the dictionary?
    • Each thread would add its own entry. Would I have to lock the dictionary while I add new thread items? If so, would I be able to use a separate lock object to allow threads to access their own data in the meantime?

    Would there be an advantage to using a concurrent dictionary? Is there another way that is more thread-safe?

    I am currently using ThreadPool.QueueUserWorkItem. I don't know for sure that this uses a new thread for each item. If not then I could also key it to the context.

    Update: According to ThreadPool class - MSDN, it does reuse threads. And it does not clear thread data.

    When the thread pool reuses a thread, it does not clear the data in thread local storage or in fields that are marked with the ThreadStaticAttribute attribute. Therefore, when a method examines thread local storage or fields that are marked with the ThreadStaticAttribute attribute, the values it finds might be left over from an earlier use of the thread pool thread.

    • Dustin Kingen
      Dustin Kingen about 11 years
      Have you tried subclassing the BackgroundWorker class?
    • Gene
      Gene about 11 years
      Because you have a distinct entry point for your worker threads and you write the worker logic yourself, it shouldn't be a problem for you to wipe the old thread data.
  • Dustin Kingen
    Dustin Kingen about 11 years
    @ArlenBeiler How many cores does your machine have? Threading every request would be pretty suboptimal. It would be better to write a request scheduler that will distribute work over some number of threads.
  • Gene
    Gene about 11 years
    Neat. Didn't know that one.
  • Arlen Beiler
    Arlen Beiler about 11 years
    So what is the difference between this method, and Gene's answer? They both apparently accomplish the same thing. I guess Gene's method could be accessed from anywhere in the Thread, whereas this one follows standard access conventions. This one is easier. +1 to both of you :)
  • ken2k
    ken2k about 11 years
    @ArlenBeiler This link should help: msdn.microsoft.com/en-us/library/6sby1byh.aspx
  • BornToCode
    BornToCode over 8 years
    @ArlenBeiler - The ThreadStatic is not only easier, it's also better performance wise.