CallContext.LogicalGetData得到恢复,即使在没有不同步。为什么? [英] CallContext.LogicalGetData gets restored even where there is no asynchrony. Why?
问题描述
我注意到 CallContext.LogicalSetData / LogicalGetData code>不工作,我希望他们做的方式。内部的
设置的值异步
方法被恢复的即使没有不同步或任何形式的线程切换,任何。
I noticed that CallContext.LogicalSetData/LogicalGetData
don't work the way I expected them to do. A value set inside an async
method gets restored even when there is no asynchrony or any kind of thread switching, whatsoever.
下面是一个简单的例子:
Here is a simple example:
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"));
}
}
}
}
它产生这样的输出:
It produces this output:
dataXX
dataX
42
dataXX
如果我让 TestAsync
非异步,它按预期工作:
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);
}
输出:
dataXX
dataX
42
dataX
我能够理解这种行为,如果我有在 TestAsync
一些真正的不同步,但这不是这里的情况。我甚至用 ExecutionContext.Sup pressFlow
,但是这并不能改变什么。
I would understand this behavior if I had some real asynchrony inside TestAsync
, but that's not the case here. I even use ExecutionContext.SuppressFlow
, but that doesn't change anything.
可能有人请解释为什么是这样工作的?
Could someone please explain why it works this way?
推荐答案
在这种情况下,正如预期的那样对于不同的人不同。 :)
"As expected" in this case is different for different people. :)
在原来的异步CTP(没有修改任何框架code),有一个异步本地之类的背景下,在所有的不支持。 MS修改 LocalCallContext
在.NET 4.5中添加这种支持。旧的行为(具有共享逻辑上下文)是<一个href="https://social.msdn.microsoft.com/Forums/en-US/ea21ca57-5340-439c-8ee9-f0185b5787a1/callcontext-what-are-the-recommendations-for-using-this-going-forwards?forum=async"相对=nofollow>特别是异步并发(即 Task.WhenAll
)。
In the original Async CTP (which did not modify any framework code), there was no support for an "async-local" kind of context at all. MS modified the LocalCallContext
in .NET 4.5 to add this support. The old behavior (with a shared logical context) is especially problematic when working with asynchronous concurrency (i.e., Task.WhenAll
).
我解释href="http://blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html" rel="nofollow"> <$ C $高级技工 LocalCallContext 在异步
的方法在我的博客。关键就在这里:
I explain the high-level mechanics of LocalCallContext
within async
methods on my blog. The key is here:
当一个异步
方法开始,它会通知其逻辑调用上下文激活副本上写的行为。
When an
async
method starts, it notifies its logical call context to activate copy-on-write behavior.
有一个特殊的副本上写标志在逻辑调用上下文多数民众赞成翻转每当异步
方法开始执行的。这是由异步
状态机(特别是,在当前的实现, AsyncMethodBuilderCore.Start
调用<$ C $完成C> ExecutionContext.EstablishCopyOnWriteScope )。而标志是一种简化 - 有没有实际的布尔成员或任何东西;它只是修改的方式,未来将写入(浅)复制的逻辑调用上下文状态( ExecutionContextBelongsToCurrentScope
和朋友)。
There's a special copy-on-write flag in the logical call context that's flipped on whenever an async
method starts executing. This is done by the async
state machine (specifically, in the current implementation, AsyncMethodBuilderCore.Start
invokes ExecutionContext.EstablishCopyOnWriteScope
). And "flag" is a simplification - there's no actual boolean member or anything; it just modifies the state (ExecutionContextBelongsToCurrentScope
and friends) in a way that any future writes will (shallow) copy the logical call context.
这是相同的状态机的方法(启动
)将调用 ExecutionContextSwitcher.Undo
只要它是与同步的一部分进行的异步
方法。这就是恢复以前的逻辑背景。
That same state machine method (Start
) will call ExecutionContextSwitcher.Undo
whenever it is done with the synchronous part of the async
method. This is what is restoring the former logical context.
这篇关于CallContext.LogicalGetData得到恢复,即使在没有不同步。为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!