2016-02-11 67 views
3

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

该方法内部:SendRequestAsyncImpl正在设置呼叫上下文,当方法返回时从断点处查询逻辑呼叫上下文时,呼叫上下文设置得很好。

然而,在下面的行中的AWAIT返回后:

Message response = await SendRequestAsyncImpl(m, true).ConfigureAwait(false); 

逻辑呼叫上下文是空的。我想可能通过设置ConfigureAwait(true)而不是false来解决问题。但是这并不能解决问题。

不要紧,我尝试流,甚至设置SendRequestAsyncImpl像内一个简单的值类型:

System.Runtime.Remoting.Messaging.CallContext.LogicalSetData("flag", true); 

不是的await后可恢复。

为什么这是从我的控制台应用程序工作?但不是来自我的单元测试?有什么不同? (我已经看到一些涉及AppDomain问题的其他堆栈溢出问题,但是我甚至无法编组一个布尔值,因为编组数据的能力似乎并不是问题所在。)

+0

您的单元测试项目的目标是什么框架版本? –

+0

好问题。它的目标是.NET 4.5 –

+0

如果用'await Task.Delay(100);'替换你的SUT,它会流动吗? –

回答

2

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

在同步代码中,逻辑CallContext 确实从流出了方法。 在异步方法CallContext确实不是流回。这是有道理的,因为.NET将如何知道我想如何在像Task.WhenAll(...)之类的情况下合并CallContext。执行下面的代码说明:

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; 
} 

打印如下:

s val: True 
test val: {null} 
test2 val: {null} 

所以,你可以看到,同步方法允许CallContext中流出,而异步方法没有。

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

希望这可以帮助别人在未来。

相关问题