• 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会获取到之前的上下文,此时会出现意料之外的问题,从现象上看报错可能会是一个概率性问题。
  • 相关阅读:
    sencha touch学习心得之FormPanel
    从零开始学习Sencha Touch MVC应用之十九
    sencha touch中datepicker的汉化
    从零开始学习Sencha Touch MVC应用之十九
    从零开始学习Sencha Touch MVC应用之十八
    sencha touch中datepicker的汉化
    sencha touch学习心得之FormPanel
    常用内置模块(二)——logging模块
    包的介绍
    常用内置模块(一)——time、os、sys、random、shutil、pickle、json
  • 原文地址:https://www.cnblogs.com/liyong-blackStone/p/10270526.html
Copyright © 2020-2023  润新知