Async在单元测试中不会在同一个线程上继续

时间:2016-09-08 08:21:38

标签: c# unit-testing async-await resharper

给出以下代码:

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

......没有运气。

1 个答案:

答案 0 :(得分:2)

等待在同一个同步上下文上运行后的任务继续,而不是在同一个线程上。对于WPF应用程序,同步上下文与调度程序关联,并且只有一个调度程序线程。因此,continuation在同一个线程上运行。在单元测试中,没有同步上下文或在您的示例中,它是与线程池关联的默认同步上下文。因此,continuation可以在线程池中的任何线程上运行。

如果要在测试中完全重现行为,则应使用单线程同步上下文之一 - DispatcherSynchronizationContext或者https://github.com/StephenCleary/AsyncEx/wiki/AsyncContext