- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我注意到 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/
我目前正在使用 Threadlocal 来保存当前用户的 ID,以便根据每个用户的 Web 请求在整个应用程序中使用。我无法在较低环境中访问 HttpContext,但想访问静态 UserId 而无需
我注意到 CallContext.LogicalSetData/LogicalGetData 没有按照我预期的方式工作。在 async 方法中设置的值会被恢复即使没有异步或任何类型的线程切换,无论如何
CallContext API 有LogicalGetData 和GetData,但是MSDN Documentation 并没有做太多解释两者之间的区别,并且当它们不同时。 有什么想法吗? 最佳答案
我是一名优秀的程序员,十分优秀!