当我呼叫WrapperAsync
AsyncLocalContext.Value
时,返回null。当我在方法之外运行相同的代码块时,在Main
方法中,AsyncLocalContext.Value
不为空(这是我所期望的)。
功能完全相同但结果不同。这是Asynclocal
类的错误还是有其他解释?
internal class Program
{
private static readonly AsyncLocal<string> AsyncLocalContext = new AsyncLocal<string>();
private static void Main()
{
const string text = "surprise!";
WrapperAsync(text).Wait();
Console.WriteLine("Get is null: " + (AsyncLocalContext.Value == null));
// AsyncLocalContext.Value is null
var value = GetValueAsync(text).Result;
AsyncLocalContext.Value = value;
Console.WriteLine("Get is null: " + (AsyncLocalContext.Value == null));
// AsyncLocalContext.Value is not null
Console.Read();
}
private static async Task WrapperAsync(string text)
{
var value = await GetValueAsync(text);
AsyncLocalContext.Value = value;
}
private static async Task<string> GetValueAsync(string text)
{
await Task.Delay(0);
return text;
}
}
答案 0 :(得分:1)
请点击此链接AsyncLocal Class on MSDN
AsyncLocal<T>
表示给定异步控制流本地的环境数据,例如异步方法
这意味着当您的代码从另一个async
方法访问时使用不同的值,例如WrapperAsync
,并且您的主线程包含其他值
[更新]
不明白的事情要理解,但这里是解释。 Control Flow in Async Programs。这就是你不希望这样做时你的线程被改变的方式。
这就是控制流如何使用async
public class Program
{
private static readonly AsyncLocal<string> AsyncLocalContext = new AsyncLocal<string>();
public static void Main(string[] args)
{
AsyncLocalContext.Value = "No surprise";
WrapperAsync("surprise!");
Console.WriteLine("Main: " + AsyncLocalContext.Value);
}
private static async void WrapperAsync(string text)
{
Console.WriteLine("WrapperAsync before: " + AsyncLocalContext.Value);
AsyncLocalContext.Value = text;
Console.WriteLine("WrapperAsync after: " + AsyncLocalContext.Value);
}
}
输出是:
WrapperAsync before: No surprise
WrapperAsync after: surprise!
Main: No surprise
[/更新]
答案 1 :(得分:0)
AsyncLocal<T>
是存储在当前线程的ExecutionContext
中的环境数据。 ExecutionContext
在异步/等待调用链中自动跨线程流动(有关详细信息,请参见Stephen Toub的blog)。应用启动时,将使用默认的ExecutionContext
,但是一旦通过AsyncLocal<T>.Value
存储了数据,就会为当前的异步调用链创建一个新的ExecutionContext
(请参见here)并将环境数据添加到其中。此新上下文将传播到下游调用。
Stephen Cleary讨论了此行为here(向下滚动到AsyncLocal部分)并指出:
[AsyncLocal]为上下文信息提供了一种“向下”传递的方式 异步调用。请注意,该值不会“向上”流动。
这就是为什么调用链上的AsyncLocal<T>
更新没有反映在上游方法中的原因。