web-dev-qa-db-fra.com

Définition d'une variable globale dans un thread - C #

J'ai un serveur HTTP que j'écris en utilisant un auditeur HTTP, et j'aimerais déclarer en quelque sorte que certaines variables sont accessibles de n'importe où dans un thread. 

  • Ma classe de serveur Web est instanciée, je ne peux donc pas utiliser de variable statique.
  • Je pourrais utiliser une variable d'instance car tout le code est dans une classe, mais ... je ne sais pas.

J'ai pensé à utiliser un dictionnaire: Dictionary</*[type of Thread ID here]*/,ThreadData>, mais je crains qu'il y ait des problèmes de thread. ThreadData serait probablement une instance de classe, mais je pourrais utiliser une structure, en fonction de ce qui serait plus efficace.

  • Si je saisis le dictionnaire avec les ID de thread et le programme afin qu'un thread puisse seulement demander sa propre entrée dans le dictionnaire, y aurait-il des problèmes liés aux threads lors de l'accès au dictionnaire?
  • Chaque fil ajouterait sa propre entrée. Devrais-je verrouiller le dictionnaire pendant que j'ajoute de nouveaux éléments de fil? Si tel est le cas, pourrais-je utiliser un objet de verrouillage distinct pour permettre aux threads d'accéder à leurs propres données entre-temps? 

Y aurait-il un avantage à utiliser un dictionnaire simultané? Y a-t-il un autre moyen qui est plus thread-safe?

J'utilise actuellement ThreadPool.QueueUserWorkItem. Je ne sais pas si cela utilise un nouveau fil pour chaque élément. Sinon, je pourrais aussi le définir en fonction du contexte. 

Update: Selon Classe ThreadPool - MSDN , il réutilise les threads. Et cela ne supprime pas les données de thread.

Lorsque le pool de threads réutilise un thread, il n'efface pas les données du stockage local du thread ou des champs marqués de l'attribut ThreadStaticAttribute. Par conséquent, lorsqu'une méthode examine le stockage local du thread ou les champs marqués avec l'attribut ThreadStaticAttribute, les valeurs trouvées peuvent être laissées par une utilisation antérieure du thread de pool de threads.

22
Arlen Beiler

Une solution consisterait à utiliser un champ statique public avec l'attribut ThreadStatic :

[ThreadStatic]
public static int ThreadSpecificStaticValue;

Un champ statique marqué avec ThreadStaticAttribute n'est pas partagé entre les threads . Chaque thread en cours d'exécution a une instance distincte du champ, Et définit et obtient indépendamment des valeurs pour ce champ. Si le champ est Accédé sur un autre thread, il contiendra une valeur différente.

33
ken2k

Vous pouvez utiliser le mécanisme de stockage intégré de la classe de thread:

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

}

Exemple de sortie:

enter image description here

Cela fonctionnera également avec les threads créés par le pool de threads.

5
Gene

Pourquoi voulez-vous créer un serveur HTTP, utilisez SignalR , semble bizarre mais répondez-y

0
TalentTuner

Si votre serveur Web est basé sur une instance, pourquoi ne pas conserver toutes les données requises? Si chaque instance est verrouillée sur un certain thread, il ne devrait y avoir aucun problème.

0
rhughes