【发布时间】:2019-08-24 02:18:27
【问题描述】:
考虑以下代码:
private static async Task Main(string[] args)
{
await SetValueInAsyncMethod();
PrintValue();
await SetValueInNonAsyncMethod();
PrintValue();
}
private static readonly AsyncLocal<int> asyncLocal = new AsyncLocal<int>();
private static void PrintValue([CallerMemberName] string callingMemberName = "")
{
Console.WriteLine($"{callingMemberName}: {asyncLocal.Value}");
}
private static async Task SetValueInAsyncMethod()
{
asyncLocal.Value = 1;
PrintValue();
await Task.CompletedTask;
}
private static Task SetValueInNonAsyncMethod()
{
asyncLocal.Value = 2;
PrintValue();
return Task.CompletedTask;
}
如果您在 .NET 4.7.2 控制台应用程序中运行此代码,您将获得以下输出:
SetValueInAsyncMethod: 1
Main: 0
SetValueInNonAsyncMethod: 2
Main: 2
我确实理解输出的差异是因为SetValueInAsyncMethod 不是真正的方法,而是由AsyncTaskMethodBuilder 执行的状态机,它在内部捕获ExecutionContext 和SetValueInNonAsyncMethod 只是一个常规方法.
但即使有了这样的理解,我仍然有一些问题:
- 这是错误/缺失功能还是有意的设计决定?
- 在编写依赖于
AsyncLocal的代码时,我是否需要担心这种行为?说,我想写我的TransactionScope-wannabe,它通过等待点传输一些环境数据。AsyncLocal够了吗? - 当涉及到在整个“逻辑代码流”中保留值时,在 .NET 中是否有任何其他替代方案可以替代
AsyncLocal和CallContext.LogicalGetData/CallContext.LogicalSetData?
【问题讨论】:
标签: c# .net async-await executioncontext