Setting a global variable in a thread - C#
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:
That'll work with threads spawned by the thread pool as well.
Related videos on Youtube
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, 2020Comments
-
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 about 11 yearsHave you tried subclassing the BackgroundWorker class?
-
Gene about 11 yearsBecause 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 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 about 11 yearsNeat. Didn't know that one.
-
Arlen Beiler about 11 yearsSo 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 about 11 years@ArlenBeiler This link should help: msdn.microsoft.com/en-us/library/6sby1byh.aspx
-
BornToCode over 8 years@ArlenBeiler - The ThreadStatic is not only easier, it's also better performance wise.