默认情况下,单元测试不捕获在其运行的SynchronizationContext
,所以如果你写的东西,如:为什么ConfigureAwait(true)在单元测试中不起作用?
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do();
WriteThread();
}
private Task Do()
{
return Task.Run(() =>
{
WriteThread();
Thread.Sleep(50);
});
}
private void WriteThread()
{
Debug.WriteLine($"CURRENT THREAD: {Thread.CurrentThread.ManagedThreadId}");
}
你获得如下输出:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 6
这是很正常的:一旦await
被调用并返回,流程不会返回到原始线程。现在
,如果我写的测试方法是这样的:
[TestMethod]
public async Task AwaitThreadSwitch()
{
WriteThread();
await Do().ConfigureAwait(true); // <-- note this change
WriteThread();
}
我希望:
CURRENT THREAD: 8
CURRENT THREAD: 6
CURRENT THREAD: 8 // <-- back to the main Thread
相反,我得到的第一个测试的结果相同。
为什么不将执行编组回到测试方法的主线程?
'ConfigureAwait'与线程无关。一点都没有。任何线程都可以执行任何任务。异步代码可以在任何线程上的“await”后重新开始,始终如此。这是迄今为止“Task”API的头号误解。我不知道它来自哪里。 –
@BenjaminHodgson:我不同意你的描述。确实,作为一个抽象,“SynchronizationContext”并不一定必须完全对应于线程。但是,这并不意味着它与他们完全没有任何关系。在Winforms或WPF的常见情况下,上下文实际上与特定的线程绑定,“await”_will_实际上总是在该线程上恢复(除非另有指示),并且事实上可以考虑线程代码正在执行。也许这种“误解”来自它并不是真正的一个。 –