Arl*_*ler 23 c# .net-4.0 thread-safety
我有一个HTTP服务器,我正在使用HTTP侦听器编写,我想以某种方式声明某些变量可以从一个线程内的任何地方访问.
我想过使用字典:Dictionary</*[type of Thread ID here]*/,ThreadData>但是我担心可能存在线程问题.ThreadData将可能是一个类的实例,但我可能会使用一个结构,取决于哪个会更有效.
使用并发字典会有优势吗?还有另一种更安全的线程方式吗?
我目前正在使用ThreadPool.QueueUserWorkItem.我不确定这会为每个项目使用一个新线程.如果没有,那么我也可以将它键入上下文.
更新:根据ThreadPool类 - MSDN,它确实重用了线程.它并没有清除线程数据.
当线程池重用线程时,它不会清除线程本地存储中或使用ThreadStaticAttribute属性标记的字段中的数据.因此,当方法检查线程本地存储或使用ThreadStaticAttribute属性标记的字段时,它找到的值可能会从先前使用的线程池线程中遗留下来.
ken*_*n2k 34
一种解决方案是使用公共静态字段,其ThreadStatic属性为:
[ThreadStatic]
public static int ThreadSpecificStaticValue;
Run Code Online (Sandbox Code Playgroud)
标记为ThreadStaticAttribute的静态字段不在线程之间共享.每个执行线程都有一个单独的字段实例,并独立设置和获取该字段的值.如果在另一个线程上访问该字段,则它将包含不同的值.
您可以使用线程类的内置存储机制:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
样本输出:

这也适用于线程池产生的线程.