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:运行应用程序,控制台输出如下:
可以看到,等待之前所赋的值,在异步上下文返回后仍然能顺利地读取。
265fb350-c1c4-4330-b432-50c196001fba|0|.0|96d5b379-7e1d-4dac-a6ba-1e50db561b04
Tags: 程序, 代码, 方法, 类, 数据
IT技术