次の方法で共有


Thread-Relative スレッドローカルストレージ: 静的フィールドとデータスロット

マネージド スレッド ローカル ストレージ (TLS) を使用して、スレッドとアプリケーション ドメインに固有のデータを格納できます。 .NET には、マネージド TLS を使用する 2 つの方法 (スレッド相対静的フィールドとデータ スロット) が用意されています。

  • コンパイル時に正確なニーズを予測できる場合は、スレッド相対静的フィールド (Visual Basic のスレッド相対 Shared フィールド) を使用します。 スレッド相対静的フィールドは、最適なパフォーマンスを提供します。 また、コンパイル時の型チェックの利点もあります。

  • 実際の要件が実行時にのみ検出される可能性がある場合は、データ スロットを使用します。 データ スロットは、スレッド相対静的フィールドよりも低速で使用が難しく、データは型 Objectとして格納されるため、使用する前に正しい型にキャストする必要があります。

アンマネージ C++ では、 TlsAlloc を使用してスロットを動的に割り当て、 __declspec(thread) を使用して、スレッド相対ストレージに変数を割り当てる必要があることを宣言します。 スレッド相対静的フィールドとデータ スロットは、この動作のマネージド バージョンを提供します。

System.Threading.ThreadLocal<T> クラスを使用して、オブジェクトが最初に使用されたときに遅延的に初期化されるスレッド ローカル オブジェクトを作成できます。 詳細については、「 遅延初期化」を参照してください。

マネージド TLS でのデータの一意性

スレッド相対静的フィールドとデータ スロットのどちらを使用する場合でも、マネージド TLS のデータはスレッドとアプリケーション ドメインの組み合わせに固有です。

  • アプリケーション ドメイン内では、両方のスレッドが同じフィールドまたはスロットを使用している場合でも、1 つのスレッドで別のスレッドのデータを変更することはできません。

  • スレッドが複数のアプリケーション ドメインから同じフィールドまたはスロットにアクセスすると、アプリケーション ドメインごとに個別の値が保持されます。

たとえば、スレッドがスレッド相対静的フィールドの値を設定し、別のアプリケーション ドメインに入り、フィールドの値を取得した場合、2 番目のアプリケーション ドメインで取得される値は、最初のアプリケーション ドメインの値とは異なります。 2 番目のアプリケーション ドメインのフィールドに新しい値を設定しても、最初のアプリケーション ドメインのフィールドの値には影響しません。

同様に、スレッドが 2 つの異なるアプリケーション ドメインで同じ名前付きデータ スロットを取得した場合、最初のアプリケーション ドメイン内のデータは、2 番目のアプリケーション ドメインのデータから独立したままになります。

Thread-Relative 静的フィールド

データの一部がスレッドとアプリケーションドメインの組み合わせに常に一意であることがわかっている場合は、静的フィールドに ThreadStaticAttribute 属性を適用します。 他の静的フィールドを使用する場合と同様に、フィールドを使用します。 フィールド内のデータは、それを使用する各スレッドに固有です。

スレッド相対静的フィールドは、データ スロットよりも優れたパフォーマンスを提供し、コンパイル時の型チェックの利点があります。

クラス コンストラクター コードは、フィールドにアクセスする最初のコンテキストの最初のスレッドで実行されることに注意してください。 同じアプリケーション ドメイン内の他のすべてのスレッドまたはコンテキストでは、フィールドが参照型の場合は null (Visual Basic ではNothing )、値型の場合は既定値に初期化されます。 そのため、クラス コンストラクターを使用してスレッド相対静的フィールドを初期化しないでください。 代わりに、スレッド相対静的フィールドの初期化を避け、 null (Nothing) または既定値に初期化されていることを前提とします。

データ スロット

.NET には、スレッドとアプリケーション ドメインの組み合わせに固有の動的データ スロットが用意されています。 データ スロットには、名前付きスロットと無名スロットの 2 種類があります。 どちらも、 LocalDataStoreSlot 構造体を使用して実装されます。

名前付きスロットと名前のないスロットの両方で、 Thread.SetData メソッドと Thread.GetData メソッドを使用して、スロット内の情報を設定および取得します。 これらは、現在実行中のスレッドのデータに対して常に動作する静的メソッドです。

名前付きスロットは、名前のないスロットへの参照を維持するのではなく、 GetNamedDataSlot メソッドに名前を渡すことで必要なときにスロットを取得できるため、便利です。 ただし、別のコンポーネントがスレッド相対ストレージに同じ名前を使用し、スレッドがコンポーネントと他のコンポーネントの両方からコードを実行すると、2 つのコンポーネントが互いのデータを破損する可能性があります。 (このシナリオでは、両方のコンポーネントが同じアプリケーション ドメインで実行されており、同じデータを共有するように設計されていないことを前提としています)。

こちらも参照ください