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