一般来说线程都是有自己上下文,变量是不共享的,这就需要线程本地存储
public static class TlsSample
{
[ThreadStatic]
public static int a;
[ThreadStatic]
public static int b;
public static void Thread1()
{
a = 1;
b = 2;
Console.WriteLine($"a={a} [From Thread1]");
Console.WriteLine($"b={b} [From Thread1]");
}
public static void Thread2()
{
a = 10;
b = 20;
Console.WriteLine($"a={a} [From Thread2]");
Console.WriteLine($"b={b} [From Thread2]");
}
public static void Run()
{
var thread1 = new Thread(Thread1);
var thread2 = new Thread(Thread2);
thread1.Start();
thread2.Start();
}
}
public class ThreadLocalSample
{
public readonly ThreadLocal<int> a = new ThreadLocal<int>();
public readonly ThreadLocal<int> b = new ThreadLocal<int>();
public void Thread1()
{
a.Value = 1;
b.Value = 2;
Console.WriteLine($"a={a} [From Thread1]");
Console.WriteLine($"b={b} [From Thread1]");
}
public void Thread2()
{
a.Value = 10;
b.Value = 20;
Console.WriteLine($"a={a} [From Thread2]");
Console.WriteLine($"b={b} [From Thread2]");
}
public void Run()
{
var thread1 = new Thread(Thread1);
var thread2 = new Thread(Thread2);
thread1.Start();
thread2.Start();
}
}
异步本地变量AsyncLocal(执行上下文)
public static class Sample07
{
private static readonly ThreadLocal<int> ThreadLocal = new ThreadLocal<int>();
private static readonly AsyncLocal<int> AsyncLocal = new AsyncLocal<int>();
public static async Task Run()
{
ThreadLocal.Value = 10;
AsyncLocal.Value = 10;
Console.WriteLine($"Tid={Thread.CurrentThread.ManagedThreadId};" +
$"ThreadLocal={ThreadLocal.Value};" +
$"AsyncLocal={AsyncLocal.Value}");
await Task.Delay(1000);
Console.WriteLine($"Tid={Thread.CurrentThread.ManagedThreadId};" +
$"ThreadLocal={ThreadLocal.Value};" +
$"AsyncLocal={AsyncLocal.Value}");
}
}
不变性值类型子任务异步变量修改不会变,引用会
public static class Sample08
{
private static readonly AsyncLocal<int> AsyncLocal = new AsyncLocal<int>();
public static async Task ParentTask()
{
AsyncLocal.Value = 111;
Console.WriteLine($"ParentTask Begin:AsyncLocal={AsyncLocal.Value}");
await ChildTask();
Console.WriteLine($"ParentTask End:AsyncLocal={AsyncLocal.Value}");
}
public static async Task ChildTask()
{
Console.WriteLine($"ChildTask Begin:AsyncLocal={AsyncLocal.Value}");
AsyncLocal.Value = 222;
await Task.Delay(1000);
Console.WriteLine($"ChildTask End:AsyncLocal={AsyncLocal.Value}");
}
}
禁止捕捉执行上下文,则无法传递到其他线程
public static class Sample11
{
private static readonly AsyncLocal<int> AsyncLocal = new AsyncLocal<int>();
public static async Task ParentTask()
{
AsyncLocal.Value = 111;
Console.WriteLine($"ParentTask Begin:AsyncLocal={AsyncLocal.Value}");
// 禁止捕捉执行上下文
var control = ExecutionContext.SuppressFlow();
Task.Delay(100).ContinueWith(task =>
{
Console.WriteLine($"SuppressFlow:AsyncLocal={AsyncLocal.Value}");
});
// 恢复捕捉上下文
control.Undo();
// 捕捉到的执行上下文为null
await Task.Delay(100);
Console.WriteLine($"Undo:AsyncLocal={AsyncLocal.Value}");
}
}