异步不会在单元测试中的同一线程上继续 [英] Async does not continue on same thread in unit test

查看:94
本文介绍了异步不会在单元测试中的同一线程上继续的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给出以下代码:

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输出将在相同的线程上运行(正如我期望的那样):

Calling the CurrentThreadCall() method from a WPF application, the Begin and Completed outputs will run on the same threads (just as I would expect):

BackgroundCall begin: 9
Task run on thread: 6
Completed on thread 9   <--- As expected

如果我从单元测试中调用该方法并使用ReSharper testrunner(VS2015中为2016.2),则Completed输出将与任务在同一线程上运行:

If I call the method from a unit test and use the ReSharper testrunner (2016.2 in VS2015), the Completed output will instead run on the same thread as the task:

Begin on thread 11
Task run on thread: 4
Completed on thread 4   <-- Not what I expected

这是为什么,我可以在测试中做些什么来使其像WPF应用程序中那样工作吗?

Why is this, and can I do something in my test to make it work like in the WPF application?

我尝试过的...

我试图使测试方法异步:

I have tried to make the test method async:

[Test]
public async Task MyTest()
{
    await CurrentThreadCall();
}

无奈之下,我试图从测试中设置 SynchronizationContext :

In desperation, I have tried to set the SynchronizationContext from the test:

[Test]
public void MyTest()
{
    SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
    CurrentThreadCall();
}

...没有运气.

推荐答案

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

Task continuations after await run on the same synchronization context, not on the same thread. For WPF applications, the synchronization context is associated with the dispatcher, and there is only one dispatcher thread. Hence continuations run on the same thread. In unit tests there either no synchronization context or as in your example, it is default sync context associated with the thread pool. Thus, continuation may run on any of the threads in the thread pool.

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

If you want to reproduce the behavior exactly in tests, you should use one of single-threaded synchronization contexts - the DispatcherSynchronizationContext or e.g. https://github.com/StephenCleary/AsyncEx/wiki/AsyncContext

这篇关于异步不会在单元测试中的同一线程上继续的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆