はじめに
今回はThreadStatic
を利用してスレッドによって異なるインスタンスが生成される静的フィールドを作成する方法を紹介したいと思います。
やり方
[ThreadStatic]
を静的フィールドにつけると、スレッドごとにインスタンスが作成されるようになります。
public class Program { [ThreadStatic] private static int ThreadStaticNum; private static int StaticNum; public static void Main(string[] args) { ThreadStaticNum = 1; StaticNum = 1; // [1] ThreadStaticNum : 1 // [1] StaticNum : 1 Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] ThreadStaticNum : {ThreadStaticNum}"); Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] StaticNum : {StaticNum}"); // 別スレッドに移動させる var task = Task.Run(() => { // [5] ThreadStaticNum : 0 // [5] StaticNum : 1 Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] ThreadStaticNum : {ThreadStaticNum}"); Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] StaticNum : {StaticNum}"); ThreadStaticNum = 2; StaticNum = 2; // [5] ThreadStaticNum : 2 // [5] StaticNum : 2 Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] ThreadStaticNum : {ThreadStaticNum}"); Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] StaticNum : {StaticNum}"); }); task.Wait(); // [1] ThreadStaticNum : 1 // [1] StaticNum : 2 Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] ThreadStaticNum : {ThreadStaticNum}"); Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] StaticNum : {StaticNum}"); } }
初期値をつけてはダメ
CA2019:ThreadStatic フィールドでインライン初期化を使用しないでください
ThreadStaticAttributeフィールドは、インライン初期化では使用せず、または static (Visual Basic では Shared) コンストラクターで明示的に初期化しないでください。 static コンストラクターは、static 型 のコンストラクターを実行するスレッドのフィールドのみを初期化します。
CA2019: 'ThreadStatic' フィールドにインライン初期化をしないでください - .NET | Microsoft Learn
// NG class C { [ThreadStatic] private static Object obj = new(); }
// OK class C { [ThreadStatic] private static Object obj; static void S1() { obj ??= new Object(); } }
staticでないフィールドはダメ
CA2259: ThreadStatic が静的フィールドでのみ使用されていることを確認してください
ThreadStaticAttributeは、フィールドの値がスレッドごとに一意であることを示し、static フィールド (Visual Basic では Shared) にのみ影響します。 インスタンス フィールドに適用した場合、 属性は動作に影響しません。
CA2259: 'ThreadStatic' が静的フィールドでのみ使用されていることを確認する - .NET | Microsoft Learn
// NG class C { [ThreadStatic] private string ThreadStaticMessage; }
// OK class C { [ThreadStatic] private static string ThreadStaticMessage; }