保留异步上下文中的本地变量值

posted at 2020.12.7 16:23 by 风信子

在基于Task的异步等待上下文中,ThreadLocal<T>类型的本地变量无法发挥作用。

请思考以下例子。

        ThreadLocal<string> local = new ThreadLocal<string>();   

        async Task WorkAsync()

        {

            local.Value = "Hello cx";

            Console.WriteLine("异步等待前:{0}", local.Value);

            await Task.Delay(150);

            Console.WriteLine("异步等待后:{0}", local.Value);

        }

在进入异步等待前,本地变量将字符串常量赋值为“Hello cx”,随后调用Delay方法,并异步等待方法返回。回到当前上下文后,本地变量的值变为默认值(字符串的默认值为null),也就是说,之前赋值的字符串“Hello cx”已经读不到了。

这是因为基于并行任务的异步上下文是由内部框架自动调度的,异步等待前后,本地变量可能处于不同的线程上,即await语句使用前后的代码并不是在同一个线程上,所以在等待方法返回后就取不到本地变量的值了。要解决这个问题,可以用AsyncLocal<T>类替换ThreadLocal<T>类。AsyncLocal<T>类能够在异步上下文之间保留原有的数据,即使异步等待的前后的代码不在同一个线程上,也能够访问之前设置的值。

以下实例将演示AsyncLocal<T>类的用法。

【操作流程】

步骤1:新建一个控制台应用程序项目。

步骤2:Program类中声明一个静态字段。

static AsyncLocal<string> local = new AsyncLocal<string>();

步骤3:定义一个异步方法。

        static async Task RunThisCodeAsync()

        {

            local.Value = "Follow me";

            Console.WriteLine("异步等待前:{0}", local.Value);

            await Task.Delay(150);

            Console.WriteLine("异步等待后:{0}", local.Value);

        }

步骤4:main方法中调用RunThisCodeAsync方法。

 RunThisCodeAsync().Wait();

步骤5:运行应用程序,控制台输出如下:

  可以看到,等待之前所赋的值,在异步上下文返回后仍然能顺利地读取。

Tags: , , , ,

IT技术

添加评论

  Country flag

biuquote
  • 评论
  • 在线预览
Loading