Freigeben über


Lokaler Threadspeicher: Thread-Relative Statische Felder und Datenslots

Sie können verwalteten threadlokalen Speicher (TLS) verwenden, um Daten zu speichern, die für einen Thread und eine Anwendungsdomäne eindeutig sind. .NET bietet zwei Möglichkeiten zum Verwenden von verwaltetem TLS: threadrelative statische Felder und Datenplätze.

  • Verwenden Sie threadbezogene statische Felder (threadbezogene Shared-Felder in Visual Basic), wenn Sie Ihre Anforderungen zum Zeitpunkt der Kompilierung exakt bestimmen können. Threadrelative statische Felder bieten die beste Leistung. Sie bieten Ihnen auch die Vorteile der Überprüfung von Kompilierungszeittypen.

  • Verwenden Sie Datenfelder, wenn Ihre tatsächlichen Anforderungen möglicherweise erst während der Laufzeit ermittelt werden. Datenslots sind langsamer und umständlicher zu verwenden als threadbezogene statische Felder, und Daten werden als Typ Object gespeichert, sodass Sie sie in den richtigen Typ umwandeln müssen, bevor Sie sie verwenden.

In nicht-verwalteten C++ verwenden Sie TlsAlloc, um Slots dynamisch zuzuweisen, und __declspec(thread), um zu deklarieren, dass eine Variable im threadrelativen Speicher zugewiesen werden soll. Threadrelative statische Felder und Datenplätze stellen die verwaltete Version dieses Verhaltens bereit.

Sie können mit der System.Threading.ThreadLocal<T>-Klasse threadlokale Objekte erstellen, die verzögert initialisiert werden, wenn das Objekt zum ersten Mal verwendet wird. Weitere Informationen finden Sie unter Lazy Initialization.

Eindeutigkeit von Daten in verwaltetem TLS

Unabhängig davon, ob Sie threadrelative statische Felder oder Datenplätze verwenden, sind Daten in verwaltetem TLS für die Kombination aus Thread- und Anwendungsdomäne eindeutig.

  • Innerhalb einer Anwendungsdomäne kann ein Thread keine Daten aus einem anderen Thread ändern, selbst wenn beide Threads dasselbe Feld oder denselben Steckplatz verwenden.

  • Wenn ein Thread von mehreren Anwendungsdomänen auf dasselbe Feld oder denselben Platz zugreift, wird in jeder Anwendungsdomäne ein separater Wert verwaltet.

Wenn ein Thread beispielsweise den Wert eines threadrelativen statischen Felds festlegt, eine andere Anwendungsdomäne eingibt und dann den Wert des Felds abruft, unterscheidet sich der in der zweiten Anwendungsdomäne abgerufene Wert vom Wert in der ersten Anwendungsdomäne. Das Festlegen eines neuen Werts für das Feld in der zweiten Anwendungsdomäne wirkt sich nicht auf den Wert des Felds in der ersten Anwendungsdomäne aus.

Wenn ein Thread denselben benannten Datenplatz in zwei verschiedenen Anwendungsdomänen erhält, bleiben die Daten in der ersten Anwendungsdomäne unabhängig von den Daten in der zweiten Anwendungsdomäne.

Thread-Relative statische Felder

Wenn Sie wissen, dass ein Datenteil immer für eine Thread- und Anwendungsdomänenkombination eindeutig ist, wenden Sie das ThreadStaticAttribute Attribut auf das statische Feld an. Verwenden Sie das Feld wie jedes andere statische Feld. Die Daten im Feld sind für jeden Thread eindeutig, der es verwendet.

Threadbezogene statische Felder bieten bessere Leistung als Datenslots und haben den Vorteil der Typüberprüfung zur Kompilierzeit.

Beachten Sie, dass jeder Klassenkonstruktorcode im ersten Thread im ersten Kontext ausgeführt wird, der auf das Feld zugreift. In allen anderen Threads oder Kontexten in derselben Anwendungsdomäne werden die Felder auf null (bzw. Nothing in Visual Basic) initialisiert, wenn sie Referenztypen sind, oder auf ihre Standardwerte, wenn sie Werttypen sind. Daher sollten Sie sich nicht auf Klassenkonstruktoren verlassen, um threadrelative statische Felder zu initialisieren. Vermeiden Sie stattdessen die Initialisierung threadrelativer statischer Felder, und gehen Sie davon aus, dass sie in null (Nothing) oder auf ihre Standardwerte initialisiert werden.

Daten-Slots

.NET stellt dynamische Datenplätze bereit, die für eine Kombination aus Thread- und Anwendungsdomäne eindeutig sind. Es gibt zwei Arten von Datenslots: benannte und nicht benannte Slots. Beide werden mithilfe der LocalDataStoreSlot Struktur implementiert.

Verwenden Sie für benannte und unbenannte Slots die Thread.SetData Und Thread.GetData Methoden, um die Informationen im Slot festzulegen und abzurufen. Dies sind statische Methoden, die immer auf die Daten für den Thread reagieren, der sie derzeit ausführt.

Benannte Slots können praktisch sein, da Sie den Steckplatz abrufen können, wenn Sie ihn benötigen, indem Sie seinen Namen an die GetNamedDataSlot Methode übergeben, anstatt einen Verweis auf einen nicht benannten Steckplatz beizubehalten. Wenn eine andere Komponente jedoch denselben Namen für den threadrelativen Speicher verwendet und ein Thread Code sowohl von Der Komponente als auch von der anderen Komponente ausführt, können die beiden Komponenten die Daten gegenseitig beschädigen. (In diesem Szenario wird davon ausgegangen, dass beide Komponenten in derselben Anwendungsdomäne ausgeführt werden und nicht für die gemeinsame Nutzung derselben Daten konzipiert sind.)

Siehe auch