Synchronization Context does not flow when using

We plan to use async / await in our MVVM viewer models, but we are facing a tough problem with the testing module of this code. When using NUnit and manual messaging, we lose the current SynchronizationContext .

This is best shown with the following small sample playback 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(); } 

In fact, most of this code is stolen from Stephen Toub's AsyncPump implementation on his blog .

Interestingly, everything needed to complete this test pass is thrown into ExecutionContext.SuppressFlow(); before calling the async method. This may be enough to fix our problem, but I do not know enough about ExecutionContext, and I need a deeper understanding of what is happening.

Why does the code generated by the wait statement swallow the current SynchronizationContext?
Is there another obvious way to use a single thread to unit test async / await code?

PS: We use .Net4 and Microsoft.CompilerServices.AsyncTargetingPack.Net4

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

+4
source share
2 answers

I had exactly the same problem.

I found out that this is due to the fact that my custom SynchronizationContext did not override or apply the CreateCopy method incorrectly. Asynchronous code seems to create a copy of the context after each task (or something else). Make sure yours use it properly too.

+1
source

You are running a bug in .NET 4.0, which is fixed in .NET 4.5:

SynchronizationContext.Current is null in the continuation of the main user interface thread

This is the same problem because the code after await will be wrapped in a sequel.

+1
source

All Articles