给出以下代码:
public static async void CurrentThreadCall()
{
Console.WriteLine("Begin on thread {0}", Thread.CurrentThread.ManagedThreadId);
await BackgroundCall();
Console.WriteLine("Completed on thread {0}", Thread.CurrentThread.ManagedThreadId);
}
private static async Task BackgroundCall()
{
await Task
.Run(() =>
{
Console.WriteLine("Task run on thread: {0}", Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(TimeSpan.FromMilliseconds(100));
})
.ConfigureAwait(false);
}
从WPF应用程序调用{{1}}方法,Begin和Completed输出将在相同的线程上运行(正如我所期望的那样):
CurrentThreadCall()
如果我从单元测试中调用该方法并使用ReSharper testrunner(VS2015中的2016.2),则Completed输出将在与任务相同的线程上运行:
BackgroundCall begin: 9
Task run on thread: 6
Completed on thread 9 <--- As expected
为什么会这样,我可以在测试中做些什么来使它像WPF应用程序一样工作吗?
我尝试了什么......
我试图让测试方法异步:
Begin on thread 11
Task run on thread: 4
Completed on thread 4 <-- Not what I expected
绝望之下,我试图从测试中set the SynchronizationContext
:
[Test]
public async Task MyTest()
{
await CurrentThreadCall();
}
......没有运气。
答案 0 :(得分:2)
等待在同一个同步上下文上运行后的任务继续,而不是在同一个线程上。对于WPF应用程序,同步上下文与调度程序关联,并且只有一个调度程序线程。因此,continuation在同一个线程上运行。在单元测试中,没有同步上下文或在您的示例中,它是与线程池关联的默认同步上下文。因此,continuation可以在线程池中的任何线程上运行。
如果要在测试中完全重现行为,则应使用单线程同步上下文之一 - DispatcherSynchronizationContext或者https://github.com/StephenCleary/AsyncEx/wiki/AsyncContext