CallContext.LogicalGetData得到恢复,即使在没有不同步。为什么?不同步、CallContext、LogicalGetData

2023-09-04 03:33:39 作者:踏平女宿舍

我注意到 CallContext.LogicalSetData / LogicalGetData 不工作,我希望他们做的方式。内部的设置的值异步方法被恢复的即使没有不同步或任何形式的线程切换,任何。

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中添加这种支持。旧的行为(具有共享逻辑上下文)是特别是异步并发(即 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">

 
精彩推荐