我有以下示例
[TestMethod]
public void AsyncLocalFlowsInContinuation()
{
AsyncLocal<int> local = new AsyncLocal<int>();
var task1 = Task.Run(() =>
{
local.Value = 1;
});
local.Value.Should().Be(0);
var t1c = task1.ContinueWith((r) =>
{
local.Value.Should().Be(1); //THROW: it is 0 instead
});
local.Value.Should().Be(0);
t1c.Wait();
}
这不应该开箱即用吗?在我的理解中,AsyncLocal应该像每个任务的静态但特定的一样(例如,适用于在“task1”中创建的子任务),但它在连续任务“t1c”中似乎没有相同的值。我应该指定一些东西来允许ExecutionContext在延续任务中正确地流动吗?或者我错过了一些obvuois?
我正在瞄准.Net Standard 2.0,这里不一定要使用AsyncLocal,如果它是错误的类型,只要测试的语义保持不变,我就会乐意使用另一个。< / p>
答案 0 :(得分:0)
晚了3年,但是无论如何...之所以发生,是因为Task
延续不是它们继续执行的Task的嵌套任务。它们在前一个任务的调用者的上下文中执行。也就是说,例如,如果您的单元测试是异步测试,则延续将是测试方法本身的嵌套Task,并且可以访问它的异步本地状态(如果有)。
这不会改变延续是否返回Task
。
但是,重要的是,如果延续确实返回了Task
,例如它使用了Task.Run
并返回了其Task
结果,那么就存在一个“技巧”表现正确:
它必须是异步lambda,并在其内部等待任务,或使用
Unwrap()
答案 1 :(得分:-1)
任务正常运行并且根据预期的执行流程。但是,问题出在AsyncLocal<T>
类,用于
表示给定异步控件的本地环境数据 流,例如异步方法。
换句话说,分配给local
变量的数据对于它所使用的线程上下文是本地的。因此,变量有三个不同的“版本”:一个用于主线程,另一个用于主线程对于第一个任务的上下文,以及最后一个继续任务。每个都有不同的价值。
如果您使用普通的整数数据类型(int
),您将获得预期的值。
请参阅以下链接以获取更多信息:
https://msdn.microsoft.com/en-us/library/dn906268(v=vs.110).aspx