使异步本地更改传播到调用函数



DotNet Fiddle link https://dotnetfiddle.net/GqA32R

我有以下示例代码来演示异步本地功能

static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
public static async Task Main()
{
// _asyncLocalString.Value = "Value 1";
var t1 = AsyncMethodA();
var t2 = AsyncMethodB();
await Task.WhenAny(t1, t2).ConfigureAwait(false);
Console.WriteLine("Finished");
Console.WriteLine("Async local inside Main: " + _asyncLocalString.Value); // null
}
static async Task AsyncMethodA()
{
// _asyncLocalString.Value = "Value 2";
Console.WriteLine("Method A");
Console.WriteLine("Async local inside A: " + _asyncLocalString.Value); // null
await Task.Delay(200);
}
static async Task AsyncMethodB()
{
_asyncLocalString.Value = "Value 3";
Console.WriteLine("Method B");
await AsyncMethodC().ConfigureAwait(false);
}
static async Task AsyncMethodC()
{
await Task.Delay(100);
Console.WriteLine("Method C");
Console.WriteLine("Async local inside C: " + _asyncLocalString.Value); // Value 3 is printed
}

输出:

Method B
Method C
Async local inside C: Value 3
Method A
Async local inside A: 
Finished
Async local inside Main: 

有没有办法将这些更改沿调用堆栈向上传播,以便 B 中的异步本地更改在 A 和 main 中可见?

我的真实场景与我上面的情况类似 - asyncLocal 仅在 methodB 中设置,我们在调用堆栈中有一些语句,它们以不同的方式记录该值。

有没有办法将这些更改传播到调用堆栈中,以便 B 中的异步本地更改在 A 和 main 中可见?

不,不是AsyncLocal<T>.async方法将其值上下文设置为"写入时复制",因此如果写入,则将创建一个副本。而且副本永远不会向上"流动"。

您将需要使用其他机制来实现您要做的任何事情。

有没有办法将这些更改传播到调用堆栈中,以便 B 中的异步本地更改在 A 和 main 中可见?

例如,您可以使用AsyncLocal<StrongBox<T>>包装实例。 这样,该值将位于最初由父级设置的实例中。

最新更新