zoukankan      html  css  js  c++  java
  • AsnycLocal与ThreadLocal

    AsnycLocal与ThreadLocal

    AsnyncLocal与ThreadLocal都是存储线程上下文的变量,但是,在实际使用过程中两者又有区别主要的表现在:

    • AsyncLocal变量可以在父子线程中传递,创建子线程时父线程会将自己的AsyncLocal类型的上下文变量赋值到子线程中,但是,当子线程改变线程上下文中AsnycLocal变量值后,父线程不会同步改变。也就是说AsnycLocal变量只会影响他的子线程,不会影响他的父级线程。
    • TreadLocal只是当前线程的上下文变量,不能在父子线程间同步。
    using System;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace await_aysnc
    {
        class Program
        {
            static ThreadLocal<int> ThreadObj = new ThreadLocal<int>();
            static AsyncLocal<int> AsyncObj = new AsyncLocal<int>();
    
            static void Main(string[] args)
            {
                AsyncObj.Value = 1;
                ThreadObj.Value = 1;
                Console.WriteLine($"Task执行前:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
                Task.Run(async() =>
                {
                    Console.WriteLine($"RunAsync异步执行前:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
                    await RunAsync();
                    Console.WriteLine($"RunAsync异步执行后:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
                });
                Console.WriteLine($"Task执行后:AsyncObj= {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
                Console.Read();
            }
    
            static async Task RunAsync()
            {           
                Console.WriteLine($"Delay异步执行前:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId} ");
                AsyncObj.Value = 2;
                ThreadObj.Value = 2;
                await Task.Delay(100);
                Console.WriteLine($"Delay异步执行后:AsyncObj = {AsyncObj.Value} ThreadObj= {ThreadObj.Value} ThreeadId = {Thread.CurrentThread.ManagedThreadId}");
            }
        }
    
    }
    
    
    Task执行前:AsyncObj= 1 ThreadObj= 1 ThreeadId = 1
    Task执行后:AsyncObj= 1 ThreadObj= 1 ThreeadId = 1
    RunAsync异步执行前:AsyncObj= 1 ThreadObj= 0 ThreeadId = 3
    Delay异步执行前:AsyncObj = 1 ThreadObj= 0 ThreeadId = 3
    Delay异步执行后:AsyncObj = 2 ThreadObj= 0 ThreeadId = 4
    RunAsync异步执行后:AsyncObj = 1 ThreadObj= 0 ThreeadId = 4
    

    从结果上可以看出一下结论:

    • RunAsync执行前ThreadLocal值被切成0即ThreadLocal变量在新线程里面没有继承主线程的上下文变量,但是AsyncLocal继承了。
    • Delay返回后,线程id变了,同时,TheadLocal中的变量为0。
    • RunAsync结束后AyncLocal又切回主线程的上下文值,,同样Threadlocal中的值丢失。
    • 由于await执行完返回之后,.net会在线程池中随机选取一个线程来执行await之后的逻辑,所以,await之后同时也会有一定几率获取到之前的线程,如果出现这种情形,TreadLocal会获取到之前的上下文,此时会出现意料之外的问题,从现象上看报错可能会是一个概率性问题。
  • 相关阅读:
    MFC Windows 程序设计>WinMain 简单Windows程序 命令行编译
    AT3949 [AGC022D] Shopping 题解
    CF643D Bearish Fanpages 题解
    CF643C Levels and Regions 题解
    CF241E Flights 题解
    CF671C Ultimate Weirdness of an Array 题解
    CF1592F Alice and Recoloring 题解
    GYM 102452E 题解
    CF494C Helping People 题解
    P5556 圣剑护符
  • 原文地址:https://www.cnblogs.com/liyong-blackStone/p/10270526.html
Copyright © 2011-2022 走看看