我有一个HTTP服务器,我正在使用HTTP侦听器编写,我想以某种方式将某些变量声明为可从线程内的任何位置访问。
我想过使用字典:Dictionary</*[type of Thread ID here]*/,ThreadData>
,但我担心可能存在线程问题。 ThreadData
可能可能是一个类实例,但我可能会使用一个结构,具体取决于哪个更有效。
使用并发字典会有优势吗?还有另一种更安全的线程吗?
我目前正在使用ThreadPool.QueueUserWorkItem
。我不确定这会为每个项目使用一个新线程。如果没有,那么我也可以将它键入上下文。
更新:根据ThreadPool class - MSDN,它确实重用了线程。并且它不会清除线程数据。
当线程池重用线程时,它不会清除线程本地存储中或使用ThreadStaticAttribute属性标记的字段中的数据。因此,当方法检查线程本地存储或使用ThreadStaticAttribute属性标记的字段时,它找到的值可能会从先前使用线程池线程中遗留下来。
答案 0 :(得分:34)
一种解决方案是使用公共静态字段,并使用ThreadStatic
属性:
[ThreadStatic]
public static int ThreadSpecificStaticValue;
标记为ThreadStaticAttribute的静态字段之间不共享 线程。每个执行线程都有一个单独的字段实例, 并独立设置并获取该字段的值。如果该字段是 在不同的线程上访问,它将包含不同的值。
答案 1 :(得分:6)
您可以使用线程类的内置存储机制:
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));
}
}
示例输出:
这也适用于线程池产生的线程。
答案 2 :(得分:0)
如果您的网络服务器是基于实例的,为什么不保留所有必需的数据呢?如果每个实例都被锁定到某个线程,那么应该没有问题。
答案 3 :(得分:-1)
你为什么要创建一个HTTP服务器,使用SignalR,看起来怪异的答案,但想一想