Threads generally have their own context and variables are not shared, which requires thread-local storage
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 = newThread(Thread2); thread1.Start(); thread2.Start(); }}Copy the code
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 = newThread(Thread2); thread1.Start(); thread2.Start(); }}Copy the code
Asynchronous local variable AsyncLocal (execution context)
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}"); }}Copy the code
Invariant value type subtask asynchronous variable modification does not change, reference does
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}"); }}Copy the code
Disallow capturing execution context and cannot be passed to other threads
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}");
// Disallows capturing execution context
var control = ExecutionContext.SuppressFlow();
Task.Delay(100).ContinueWith(task =>
{
Console.WriteLine($"SuppressFlow:AsyncLocal={AsyncLocal.Value}");
});
// Restore the capture context
control.Undo();
// The execution context captured is NULL
await Task.Delay(100);
Console.WriteLine($"Undo:AsyncLocal={AsyncLocal.Value}"); }}Copy the code