LogicalCallContext在Console App中流过await但不在VS UnitTest中流动

Ayo*_*o I 6 c# remoting vs-unit-testing-framework async-await

我正在使用Logical CallContext在一系列等待中回传信息.有趣的是,在我的测试控制台应用程序中,一切正常.但是,当在VS UnitTest的上下文中运行我的单元测试时,调用上下文似乎没有流过等待.

方法内部:SendRequestAsyncImpl正在设置调用上下文,当我在方法返回时从断点查询逻辑调用上下文时,调用上下文设置得很好.

但是,在await返回以下行之后:

Message response = await SendRequestAsyncImpl(m, true).ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

逻辑调用上下文为空.我想也许可以通过设置ConfigureAwait(true)而不是false来解决问题.但这并不能解决问题.

无论我尝试流动什么,甚至在SendRequestAsyncImpl中设置一个简单的值类型,如:

System.Runtime.Remoting.Messaging.CallContext.LogicalSetData("flag", true);
Run Code Online (Sandbox Code Playgroud)

await后无法检索.

为什么这可以从我的控制台应用程序工作 但不是从我的单元测试?有什么不同?(我已经看到了其他一些涉及AppDomain问题的堆栈溢出问题.但是我甚至无法在整个等待期间编组一个bool.编组数据的能力似乎不是问题.)

Ayo*_*o I 7

因此,在阅读了 Stephen Clearly 在这个问题和文章中的评论后:http : //blog.stephencleary.com/2013/04/implicit-async-context-asynclocal.html答案已经变得清晰。

而在同步代码中,逻辑 CallContext确实从方法流出。在异步方法CallContext中并没有回流出。这是有道理的,因为 .NET 如何知道我希望 CallContext 在像 Task.WhenAll(...) 这样的事情之后被合并。执行以下代码说明:

static void Main(string[] args)
{
    SynchronousCall();
    Task.WaitAll(Test(), Test2());
    var s = CallContext.LogicalGetData("SynchronousCall");
    var test = CallContext.LogicalGetData("Test");
    var test2 = CallContext.LogicalGetData("Test2");

    Console.WriteLine("s val: {0}", (s == null) ? "{null}" : s);
    Console.WriteLine("test val: {0}", (test == null) ? "{null}" : test);
    Console.WriteLine("test2 val: {0}", (test2 == null) ? "{null}" : test2);
}

private static void SynchronousCall()
{
    CallContext.LogicalSetData("SynchronousCall", true);
}

private static async Task<bool> Test()
{
    CallContext.LogicalSetData("Test", true);
    var b = await Task.Run<bool>(() => 
    {
        return true; 
    });
    return b;
}

private static async Task<bool> Test2()
{
    CallContext.LogicalSetData("Test2", true);
    var b = await Task.Run<bool>(() =>
    {
        return true;
    });
    return b;
}
Run Code Online (Sandbox Code Playgroud)

打印以下内容:

s val: True
test val: {null}
test2 val: {null}
Run Code Online (Sandbox Code Playgroud)

所以,如你所见,同步方法允许 CallContext 流出,而异步方法则不允许。

我修改了我的方法,在 awaitable 方法之前将线程安全集合注入到 CallContext 中。我将信息注入该集合,而不是直接注入 CallContext。由于上游和下游都获得对同一个集合的引用,这允许我通过在等待方法返回后从集合中检索上下文来将上下文从等待方法中流出

希望这有助于将来的其他人。