使用await时不流动SynchronizationContext [英] SynchronizationContext is not flowed when using await
问题描述
我们计划在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屋!