当前位置: 首页 > 编程语言 > C#

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

时间:2023-04-10 11:51:57 C#

CallContext.LogicalGetData即使没有异步也能恢复。为什么?我注意到CallContext.LogicalSetData/LogicalGetData没有按我预期的方式工作。即使没有异步或任何类型的线程切换,异步方法中设置的值也会被恢复。这是一个简单的例子:使用系统;使用System.Runtime.Remoting.Messaging;使用系统线程;使用System.Threading.Tasks;namespaceConsoleApplication{classProgram{staticasyncTaskTestAsync(){CallContext.LogicalSetData("valueX","dataX");//故意注释掉//awaitTask.FromResult(0);Console.WriteLine(CallContext.LogicalGetData("valueX"));返回42;}staticvoidMain(string[]args){using(ExecutionContext.SuppressFlow()){CallContext.LogicalSetData("valueX","dataXX");Console.WriteLine(CallContext.LogicalGetData("valueX"));Console.WriteLine(TestAsync().Result);安慰。WriteLine(CallContext.LogicalGetData("valueX"));它产生这个输出:dataXXDATAX42dataXX如果我使TestAsync非异步它按预期工作:staticTaskTestAsync(){CallContext.LogicalSetData("valueX","dataX");Console.WriteLine(CallContext.LogicalGetData("valueX"));返回Task.FromResult(42);}输出:dataXXDATAX42DATAX如果我在TestAsync中有一些真正的异步,我会理解这种行为,但事实并非如此。我什至使用了ExecutionContext.SuppressFlow,但这并没有改变任何东西。有人可以解释为什么它以这种方式工作吗?在这种情况下,“如预期”对不同的人意味着不同的事情。?在原始的AsyncCTP中(没有修改任何框架代码),根本不支持“async-native”类型的上下文。MS在.NET4.5中修改了LocalCallContext以添加此支持。使用异步并发(即Task.WhenAll)时Task.WhenAll的旧行为(使用共享逻辑上下文)。我在我的博客上用异步方法解释了LocalCallContext的高级机制。关键在于:当异步方法启动时,它会通知其逻辑调用上下文以激活写时复制行为。逻辑调用上下文中有一个特殊的写时复制标志,只要异步方法开始执行,该标志就会打开。这是由异步状态机完成的(具体而言,在当前实现中,AsyncMethodBuilderCore.Start调用ExecutionContext.EstablishCopyOnWriteScope)。而“标志”是一种简化——没有实际的布尔成员或任何东西;它只是修改状态(ExecutionContextBelongsToCurrentScope和朋友),以便任何未来的写入都会(浅)将逻辑复制到调用上下文。每当异步方法的同步部分完成时,相同的状态机方法(Start)将调用ExecutionContextSwitcher.Undo。这是为了恢复之前的逻辑环境。以上就是C#学习教程:即使没有异步,CallContext.LogicalGetData也会恢复。为什么?如果分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: