2013-03-14 12 views
21

Ich habe einen HTTP-Server, den ich schreibe mit HTTP-Listener, und ich möchte irgendwie Variablen als zugänglich von überall innerhalb eines Threads deklarieren.Festlegen einer globalen Variable in einem Thread - C#

  • Meine Webserver-Klasse ist instanzbasiert, daher kann ich keine statische Variable verwenden.
  • Ich könnte eine Instanzvariable verwenden, da der gesamte Code in einer Klasse ist, aber ... ich weiß es nicht.
  • Ich dachte an ein Wörterbuch: Dictionary</*[type of Thread ID here]*/,ThreadData>, aber ich bin besorgt, es könnte Threading-Probleme sein. ThreadData würde wahrscheinlich eine Klasseninstanz sein, aber ich könnte eine Struktur verwenden, je nachdem, welche effizienter wäre.

    • Wenn ich das Wörterbuch zu den Themen-IDs eingeben würde und programmieren Sie es so, dass ein Thread würde nur für einen eigenen Eintrag fragt im Wörterbuch, würde jeder Thread Probleme im Zusammenhang mit dabei sein, wenn das Wörterbuch zugreifen?
    • Jeder Thread würde seinen eigenen Eintrag hinzufügen. Müsste ich das Wörterbuch sperren, während ich neue Thread-Einträge hinzufüge? Wenn ja, wäre ich in der Lage, ein separates Sperrobjekt zu verwenden, damit Threads in der Zwischenzeit auf ihre eigenen Daten zugreifen können?

    Wäre es von Vorteil, ein Concurrent Dictionary zu verwenden? Gibt es einen anderen Weg, der threadsicherer ist?

    Ich verwende derzeit ThreadPool.QueueUserWorkItem. Ich weiß nicht sicher, dass dies für jeden Artikel einen neuen Thread verwendet. Wenn nicht, könnte ich es auch in den Kontext eintasten.

    Update: Nach ThreadPool class - MSDN, es Wiederverwendung Threads. Und es löscht Thread-Daten nicht.

    Wenn der Threadpool einen Thread wiederverwendet, werden die Daten im lokalen Threadspeicher oder in Feldern, die mit dem ThreadStaticAttribute-Attribut markiert sind, nicht gelöscht. Wenn eine Methode lokale Thread-Speicher oder Felder untersucht, die mit dem ThreadStaticAttribute-Attribut markiert sind, können die gefundenen Werte daher von einer früheren Verwendung des Thread-Pool-Threads übrig bleiben.

    +0

    Haben Sie versucht, die Subklassen [Background] (http://msdn.microsoft.com/en- us/library/system.componentmodel.backgroundworker.aspx) Klasse? – Romoku

    +0

    Da Sie einen eindeutigen Einstiegspunkt für Ihre Worker-Threads haben und Sie die Worker-Logik selbst schreiben, sollte es kein Problem für Sie sein, die alten Thread-Daten zu löschen. – Gene

    Antwort

    27

    Eine Lösung wäre ein öffentliches statisches Feld zu verwenden, mit dem ThreadStatic Attribute:

    [ThreadStatic] 
    public static int ThreadSpecificStaticValue; 
    

    Ein statisches Feld mit Thread markiert ist zwischen Fäden geteilt. Jeder ausführende Thread verfügt über eine separate Instanz des Felds und legt unabhängig voneinander Werte für dieses Feld fest. Wenn das Feld in einem anderen Thread aufgerufen wird, wird es einen anderen Wert enthalten.

    +0

    Ordentlich. Ich kannte das nicht. – Gene

    +0

    Noch ich wünschte, ich könnte +2! –

    +0

    Was ist der Unterschied zwischen dieser Methode und Genes Antwort? Sie beide machen anscheinend dasselbe. Ich denke, dass auf die Methode von Gene von überall im Thread zugegriffen werden kann, während diese der Standardzugriffskonvention folgt. Dieser ist einfacher. +1 an euch beide :) –

    0

    Wenn Ihr Webserver instanzbasiert ist, warum halten Sie nicht alle erforderlichen Daten dort? Wenn jede Instanz an einen bestimmten Thread gebunden ist, sollte es kein Problem geben.

    +0

    Nein, jede Clientanfrage erhält ihren eigenen Thread. –

    +0

    @ArlenBeiler Wie viele Kerne hat Ihre Maschine? Threading jeder Anfrage wäre ziemlich suboptimal. Es wäre besser, einen Request-Scheduler zu schreiben, der die Arbeit über eine bestimmte Anzahl von Threads verteilt. – Romoku

    +0

    Tut mir leid, es verwendet 'ThreadPool.QueueUserWorkItem'. Mein Fehler. –

    5

    Sie könnten die eingebauten Speichermechanismus der Thread-Klasse verwenden:

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

    Beispielausgabe:

    enter image description here

    Die mit Themen von dem Thread-Pool als auch gelaicht arbeiten werde.

    0

    Warum Sie das tun wollen einen HTTP-Server erstellen, verwenden Sie SignalR sieht Antwort Weirdo aber darüber nachdenken, es

    Verwandte Themen