使用await时不流动SynchronizationContext [英] SynchronizationContext is not flowed when using await

查看:99
本文介绍了使用await时不流动SynchronizationContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们计划在MVVM视图模型中使用async/await,但是在对该代码进行单元测试时遇到了一个难题.当使用NUnit和手写的模拟进行消息传递时,我们将丢失当前的SynchronizationContext.

We´re planning to use async/await in our MVVM view models, but hit a hard issue with unit testing this code. When using NUnit and a hand written mock for our messaging we´re losing the current SynchronizationContext.

最佳显示,并附有以下小型复制示例代码:

Best shown with following small reproducing example code:

[Test] public void TestMethod()
{       
  Func<Task> asyncMethod = async () =>
    {
      var context = SynchronizationContext.Current;
      await TaskEx.Yield();
      Assert.AreEqual(context, SynchronizationContext.Current);
    };

    // Establish the new context
    var syncCtx = new SingleThreadSynchronizationContext(false);
    SynchronizationContext.SetSynchronizationContext(syncCtx);

    // Invoke the function and alert the context to when it completes
    var t = asyncMethod();
    t.ContinueWith(delegate { syncCtx.Complete(); }, TaskScheduler.Default);

    // Pump continuations and propagate any exceptions
    syncCtx.RunOnCurrentThread();
    t.GetAwaiter().GetResult();
}

实际上,大多数代码是从Stephen Toub的AsyncPump实现中窃取的

Actually most of this code is stolen from the AsyncPump implementation from Stephen Toub on his blog.

要使此测试通过,需要引起兴趣的所有事情是在调用async方法之前将ExecutionContext.SuppressFlow();扔掉.这可能足以解决我们的问题,但是我对ExecutionContext的了解还不够,我想更深入地了解正在发生的事情.

Interestling all needed to make this test pass is tossing in a ExecutionContext.SuppressFlow(); before calling the async method. This could be enough to fix our Problem, but i do not know enough about ExecutionContext and i want some deeper understanding what´s going on.

为什么await语句生成的代码会吞噬当前的SynchronizationContext?
使用单线程上下文对异步/等待代码进行单元测试是否还有另一种明显的方法?

Why does the code generated by the await statement swallow the current SynchronizationContext?
Is there another obvious way in using a single threaded context for unit testing async/await code?

PS:我们正在使用.Net4和Microsoft.CompilerServices.AsyncTargetingPack.Net4

PS: We´re using .Net4 and Microsoft.CompilerServices.AsyncTargetingPack.Net4

PPS:在使用稳定的Microsoft.Bcl.Async而不是ATP的简单项目中,也会发生这种情况

PPS: This also occurs in a simple project using the stable Microsoft.Bcl.Async instead of the ATP

推荐答案

我遇到了完全相同的问题.

I had exactly same problem.

我发现这是因为我的自定义SynchronizationContext没有正确覆盖并实现CreateCopy方法.似乎异步代码会在每个任务(或某些任务)之后创建上下文的副本.确保您也正确实施了该程序.

I found out it is because my custom SynchronizationContext didn't properly override and implement CreateCopy method. It seems the async code creates copy of the context after every task (or something). Make sure yours implements it properly too.

这篇关于使用await时不流动SynchronizationContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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