异步不会在单元测试中的同一线程上继续
Async does not continue on same thread in unit test
给定以下代码:
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 应用程序调用 CurrentThreadCall()
方法,Begin 和 Completed 输出将 运行 在相同的线程上(正如我所期望的):
BackgroundCall begin: 9
Task run on thread: 6
Completed on thread 9 <--- As expected
如果我从单元测试调用该方法并使用 ReSharper 测试运行ner(VS2015 中的 2016.2),Completed 输出将改为 运行 在与任务相同的线程上:
Begin on thread 11
Task run on thread: 4
Completed on thread 4 <-- Not what I expected
为什么会这样,我可以在我的测试中做一些事情让它像在 WPF 应用程序中一样工作吗?
我试过的...
我试过使测试方法异步:
[Test]
public async Task MyTest()
{
await CurrentThreadCall();
}
无奈之下,我曾尝试set the SynchronizationContext
自考:
[Test]
public void MyTest()
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
CurrentThreadCall();
}
...运气不好。
await 运行 之后的任务继续在同一个同步上下文中,而不是在同一个线程中。对于 WPF 应用程序,同步上下文与调度程序相关联,并且只有一个调度程序线程。因此,同一线程上的延续 运行。在单元测试中,没有同步上下文,或者在您的示例中,它是与线程池关联的默认同步上下文。因此,可以在线程池中的任何线程上继续 运行。
如果您想在测试中完全重现该行为,您应该使用单线程同步上下文之一 - DispatcherSynchronizationContext 或例如https://github.com/StephenCleary/AsyncEx/wiki/AsyncContext
给定以下代码:
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 应用程序调用 CurrentThreadCall()
方法,Begin 和 Completed 输出将 运行 在相同的线程上(正如我所期望的):
BackgroundCall begin: 9
Task run on thread: 6
Completed on thread 9 <--- As expected
如果我从单元测试调用该方法并使用 ReSharper 测试运行ner(VS2015 中的 2016.2),Completed 输出将改为 运行 在与任务相同的线程上:
Begin on thread 11
Task run on thread: 4
Completed on thread 4 <-- Not what I expected
为什么会这样,我可以在我的测试中做一些事情让它像在 WPF 应用程序中一样工作吗?
我试过的...
我试过使测试方法异步:
[Test]
public async Task MyTest()
{
await CurrentThreadCall();
}
无奈之下,我曾尝试set the SynchronizationContext
自考:
[Test]
public void MyTest()
{
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
CurrentThreadCall();
}
...运气不好。
await 运行 之后的任务继续在同一个同步上下文中,而不是在同一个线程中。对于 WPF 应用程序,同步上下文与调度程序相关联,并且只有一个调度程序线程。因此,同一线程上的延续 运行。在单元测试中,没有同步上下文,或者在您的示例中,它是与线程池关联的默认同步上下文。因此,可以在线程池中的任何线程上继续 运行。
如果您想在测试中完全重现该行为,您应该使用单线程同步上下文之一 - DispatcherSynchronizationContext 或例如https://github.com/StephenCleary/AsyncEx/wiki/AsyncContext