在线程中设置全局变量 - C#

时间:2013-03-14 16:05:03

标签: c# .net-4.0 thread-safety

我有一个HTTP服务器,我正在使用HTTP侦听器编写,我想以某种方式将某些变量声明为可从线程内的任何位置访问。

  • 我的webserver类是基于实例的,所以我不能真正使用静态变量。
  • 我可以使用实例变量,因为所有代码都在一个类中,但是......我不知道。

我想过使用字典:Dictionary</*[type of Thread ID here]*/,ThreadData>,但我担心可能存在线程问题。 ThreadData 可能可能是一个类实例,但我可能会使用一个结构,具体取决于哪个更有效。

  • 如果我将字典键入线程ID并对其进行编程,以便一个线程只 在字典中询问自己的条目,那么在访问字典时是否会出现与线程相关的问题?
  • 每个帖子都会添加自己的条目。在添加新的线程项时,我是否必须锁定字典?如果是这样,我是否能够使用单独的锁对象来允许线程同时访问自己的数据?

使用并发字典会有优势吗?还有另一种更安全的线程吗?

我目前正在使用ThreadPool.QueueUserWorkItem。我不确定这会为每个项目使用一个新线程。如果没有,那么我也可以将它键入上下文。

更新:根据ThreadPool class - MSDN,它确实重用了线程。并且它不会清除线程数据。

  

当线程池重用线程时,它不会清除线程本地存储中或使用ThreadStaticAttribute属性标记的字段中的数据。因此,当方法检查线程本地存储或使用ThreadStaticAttribute属性标记的字段时,它找到的值可能会从先前使用线程池线程中遗留下来。

4 个答案:

答案 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));
  }

}

示例输出:

enter image description here

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

答案 2 :(得分:0)

如果您的网络服务器是基于实例的,为什么不保留所有必需的数据呢?如果每个实例都被锁定到某个线程,那么应该没有问题。

答案 3 :(得分:-1)

你为什么要创建一个HTTP服务器,使用SignalR,看起来怪异的答案,但想一想