gpt4 book ai didi

c# - 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?

转载 作者:太空狗 更新时间:2023-10-30 00:23:59 25 4
gpt4 key购买 nike

我注意到 CallContext.LogicalSetData/LogicalGetData 没有按照我预期的方式工作。在 async 方法中设置的值会被恢复即使没有异步或任何类型的线程切换,无论如何。

这是一个简单的例子:

using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication
{
class Program
{
static async Task<int> TestAsync()
{
CallContext.LogicalSetData("valueX", "dataX");
// commented out on purpose
// await Task.FromResult(0);
Console.WriteLine(CallContext.LogicalGetData("valueX"));
return 42;
}

static void Main(string[] args)
{
using(ExecutionContext.SuppressFlow())
{
CallContext.LogicalSetData("valueX", "dataXX");
Console.WriteLine(CallContext.LogicalGetData("valueX"));
Console.WriteLine(TestAsync().Result);
Console.WriteLine(CallContext.LogicalGetData("valueX"));
}
}
}
}

它产生这个输出:

dataXXdataX42dataXX

If I make TestAsync non-async, it works as expected:

static Task<int> TestAsync()
{
CallContext.LogicalSetData("valueX", "dataX");
Console.WriteLine(CallContext.LogicalGetData("valueX"));
return Task.FromResult(42);
}

输出:

dataXXdataX42dataX

如果我在 TestAsync 中有一些真正的异步,我会理解这种行为,但这里不是这种情况。我什至使用 ExecutionContext.SuppressFlow,但这并没有改变任何东西。

谁能解释一下为什么会这样?

最佳答案

这种情况下的“如预期”对于不同的人来说是不同的。 :)

在最初的异步 CTP(未修改任何框架代码)中,根本不支持“异步本地”类型的上下文。 MS 修改了 .NET 4.5 中的 LocalCallContext 以添加此支持。旧行为(具有共享逻辑上下文)是 especially problematic when working with asynchronous concurrency (i.e., Task.WhenAll) .

我解释了high-level mechanics of LocalCallContext within async methods在我的博客上。关键在这里:

When an async method starts, it notifies its logical call context to activate copy-on-write behavior.

只要 async 方法开始执行,逻辑调用上下文中就有一个特殊的写时复制标志。这是由 async 状态机完成的(具体而言,在当前实现中,AsyncMethodBuilderCore.Start 调用 ExecutionContext.EstablishCopyOnWriteScope)。而“标志”是一种简化——没有实际的 bool 成员或任何东西;它只是修改状态(ExecutionContextBelongsToCurrentScope 和 friend ),任何 future 的写入都会(浅)复制逻辑调用上下文。

每当使用 async 方法的同步部分完成时,相同的状态机方法 (Start) 将调用 ExecutionContextSwitcher.Undo。这就是在恢复以前的逻辑上下文。

关于c# - 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31408515/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com