ThreadLocal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| static ThreadLocal<string> LocalString = new ThreadLocal<string>();
static async Task Main(string[] args) { LocalString.Value = "Value 1"; Console.WriteLine($"【A】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
var t1 = AsyncMethod();
Console.WriteLine($"【D】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
await t1; }
static async Task AsyncMethod() { Console.WriteLine($"【B】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
LocalString.Value = "Value 3"; Console.WriteLine($"【C】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
await Task.Delay(100);
Console.WriteLine($"【E】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}"); }
|
ThreadLocal 非常容易理解, 每個 Thread 之間彼此是隔離的, 即便 ExcutionContext 不同, 但只要是同一個 Thread 都會是共用的。
所以可以看到 await 之後, 因為不同 Thread 執行剩下的 Code , ThreadLocal 的值就變成預設的空值
AsyncLocal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| static AsyncLocal<string> LocalString = new AsyncLocal<string>();
static async Task Main(string[] args) { LocalString.Value = "Value 1"; Console.WriteLine($"【A】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
var t1 = AsyncMethod();
Console.WriteLine($"【D】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
await t1; }
static async Task AsyncMethod() { Console.WriteLine($"【B】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
LocalString.Value = "Value 3"; Console.WriteLine($"【C】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}");
await Task.Delay(100);
Console.WriteLine($"【E】 Thread: {Thread.CurrentThread.ManagedThreadId}, ExcutionContext: {Thread.CurrentThread.ExecutionContext.GetHashCode()} ,value: {LocalString.Value}"); }
|
AsyncLocal 會在每次需要切出 ExcutionContext 時複製一份給新的 ExcutionContext , 所以每個 ExcutionContext間的 AsyncLocal 都是獨立的,但同時可達跨 Thread , ExcutionContext 往下傳遞的特性。