Freigeben über


Lokaler Threadspeicher: Threadbezogene statische Felder und Datenslots

Verwaltete lokale Threadspeicher (TLS) können zur Speicherung von Daten verwendet werden, die für einen Thread und eine Anwendungsdomäne eindeutig sind. .NET Framework bietet zwei Möglichkeiten zur Verwendung verwalteter lokaler Threadspeicher: threadbezogene statische Felder und Datenslots.

  • Verwenden Sie threadbezogene statische Felder (threadbezogene Shared-Felder in Visual Basic), wenn Sie die Anforderungen zur Kompilierzeit genau einschätzen können. Threadbezogene statische Felder bieten die beste Leistung. Außerdem ermöglichen sie die Typüberprüfung zur Kompilierzeit.

  • Verwenden Sie Datenslots, wenn Sie die tatsächlichen Anforderungen unter Umständen erst zur Laufzeit kennen. Datenslots sind langsamer und umständlicher als threadbezogene statische Felder. Außerdem werden die Daten als Object-Typ gespeichert, sodass Sie sie vor der Verwendung in den richtigen Typ umwandeln müssen.

In nicht verwaltetem C++ wird TlsAlloc verwendet, um Slots dynamisch zuzuweisen, und __declspec(thread), um zu deklarieren, dass eine Variable in threadbezogenem Speicher zugewiesen werden soll. Threadbezogene statische Felder und Datenslots stellen die verwaltete Version dieses Verhaltens bereit.

In .NET Framework, Version 4 können Sie threadlokale Objekte, die spät initialisiert werden, mithilfe der System.Threading.ThreadLocal<T>-Klasse erstellen, sobald das Objekt erstmals genutzt wird. Weitere Informationen finden Sie unter Verzögerte Initialisierung.

Eindeutigkeit der Daten im verwalteten TLS

Die Daten im verwalteten TLS sind für die Kombination aus Thread und Anwendungsdomäne eindeutig, und zwar unabhängig davon, ob Sie threadbezogene statische Felder oder Datenslots verwenden.

  • Innerhalb einer Anwendungsdomäne kann ein Thread die Daten eines anderen Threads nicht ändern, auch wenn beide Threads das gleiche Feld oder den gleichen Slot verwenden.

  • Wenn ein Thread aus mehreren Anwendungsdomänen auf das gleiche Feld oder den gleichen Slot zugreift, wird in jeder Anwendungsdomäne ein separater Wert beibehalten.

Wenn z. B. ein Thread den Wert eines threadbezogenen statischen Felds festlegt, in eine andere Anwendungsdomäne wechselt und anschließend den Wert des Felds abruft, unterscheidet sich der in der zweiten Anwendungsdomäne abgerufene Wert von dem Wert in der ersten Anwendungsdomäne. Wenn für das Feld in der zweiten Anwendungsdomäne ein neuer Wert festgelegt wird, hat dies keine Auswirkungen auf den Wert des Felds in der ersten Anwendungsdomäne.

Ähnlich verhält es sich, wenn ein Thread den gleichen benannten Datenslot in zwei verschiedenen Anwendungsdomänen abruft: Die Daten in der ersten Anwendungsdomäne sind unabhängig von den Daten in der zweiten Anwendungsdomäne.

Threadbezogene statische Felder

Wenn Sie wissen, dass bestimmte Daten für eine Kombination aus Thread und Anwendungsdomäne stets eindeutig sind, wenden Sie das ThreadStaticAttribute-Attribut auf das statische Feld an. Die Verwendung des Felds unterscheidet sich nicht von der eines anderen statischen Felds. Die Daten im Feld sind für jeden Thread, der sie verwendet, eindeutig.

Threadbezogene statische Felder bieten eine bessere Leistung als Datenslots und ermöglichen zudem die Typüberprüfung zur Kompilierzeit.

Beachten Sie, dass jeder Klassenkonstruktorcode auf dem ersten Thread im ersten Kontext ausgeführt wird, der auf das Feld zugreift. In allen anderen Threads oder Kontexten in der gleichen Anwendungsdomäne werden die Felder mit null (Nothing in Visual Basic) initialisiert, wenn sie Referenztypen sind, oder mit ihren Standardwerten, wenn es sich um Werttypen handelt. Daher sollten Sie die Initialisierung threadbezogener statischer Felder nicht von Klassenkonstruktoren abhängig machen. Stattdessen sollten Sie threadbezogene statische Felder nach Möglichkeit nicht initialisieren und davon ausgehen, dass sie mit null (Nothing) oder mit ihren Standardwerten initialisiert werden.

Datenslots

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

Verwenden Sie für benannte und unbenannte Datenslots die Thread.SetData-Methode und die Thread.GetData-Methode, um die Informationen im Slot festzulegen und abzurufen. Hierbei handelt es sich um statische Methoden, die stets auf die Daten für den Thread angewendet werden, der sie zurzeit ausführt.

Benannte Slots können von Vorteil sein, da Sie den Slot bei Bedarf abrufen können, indem Sie seinen Namen an die GetNamedDataSlot-Methode übergeben, anstatt einen Verweis auf einen unbenannten Slot beizubehalten. Wenn jedoch eine andere Komponente den gleichen Namen für ihren threadbezogenen Speicher verwendet und ein Thread Code sowohl aus Ihrer Komponente als auch aus der anderen Komponente ausführt, können die beiden Komponenten die Daten der jeweils anderen Komponente beschädigen. (In diesem Szenario wird davon ausgegangen, dass beide Komponenten in der gleichen Anwendungsdomäne ausgeführt werden und nicht zur Verwendung der gleichen Daten vorgesehen sind.)

Siehe auch

Referenz

ContextStaticAttribute

Thread.GetNamedDataSlot

ThreadStaticAttribute

CallContext

Weitere Ressourcen

Verwaltetes Threading