Using Visual Studio 2015 Update 3 and a C# Test project targeting .NET 4.6.1 I get the following behavior:
[TestClass]
public class AwaitTests
{
[TestMethod]
public void AsyncRemovingSyncContext_PartialFail()
{
Log("1");
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
Log("2");
HasAwait().Wait(); // The continuation in this method is on wrong thread
Log("5");
Assert.IsNotNull(SynchronizationContext.Current);
}
[TestMethod]
public async Task AsyncRemovingSyncContext_Fail()
{
Log("1");
SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
Log("2");
await HasAwait();
Log("5"); // Issue is here - Sync Context is now null
Assert.IsNotNull(SynchronizationContext.Current);
}
public async Task HasAwait()
{
Log("3");
await Task.Delay(300);
Log("4");
}
private void Log(string text)
{
Console.WriteLine($"{text} - Thread {System.Threading.Thread.CurrentThread.ManagedThreadId} - {SynchronizationContext.Current}");
}
}
Here is the output:
AsyncRemovingSyncContext_PartialFail
1 - Thread 7 -
2 - Thread 7 - System.Threading.SynchronizationContext
3 - Thread 7 - System.Threading.SynchronizationContext
4 - Thread 8 -
5 - Thread 7 - System.Threading.SynchronizationContext
AsyncRemovingSyncContext_Error
1 - Thread 7 -
2 - Thread 7 - System.Threading.SynchronizationContext
3 - Thread 7 - System.Threading.SynchronizationContext
4 - Thread 8 -
5 - Thread 8 -
-Assert Exception Thrown-
I've done other tests and so far there is a 100% correlation between the existence of the await
keyword in the method and the clearing of the Sync Context. This includes async lambdas.
This is important to me because it appears that as soon as an await
is encountered, the sync context is removed. This means that if I perform two await
s in the same method, the second continuation will just run in the thread pool (default behavior when no Sync Context).
Is this a framework/compiler bug or am I doing something wrong?
For specifics, since I'm sure someone will ask in one form or another, I have an Active Object that I would like to enable async
\ await
support for, but I can only do that if I can guarentee that the continuation will be dispatched to my ActiveObjectSynchronizationContext
, which at the moment, it's not because it's being cleared.
I've already looked at this question (and similar about the UI context 4.0 bug) but this isn't related since I'm running 4.6.1 and I'm using non-UI threads.
I also followed the advice from this other question and ensured my Sync Context implements CreateCopy
, but I can tell from test profiling that the method isn't even called.