I'm making some tests with async await since one of my unit tests was not returning at all, unless i would add a ConfigureAwait(false); to one of the involved tasks. Well I decided to find out what exactly is happening there and I wrote the following test. I'm not sure why, but the anonymous call (3.) blocks, while 1 & 2 do not.
I'm trying to check the differences with ilspy but I think it would be interesting to get some opinions on this behavior. I'm running on vs 2017 .net 4.5.2. I know that async void is bad... this is not the point here.
[Edit] I have added some more details so you can see there is no SyncContext at all at the beginning as this is a CONSOLE app. Besides, this kind of problem has been posted long time ago here: https://blog.stephencleary.com/2012/02/async-console-programs.html
internal class Program
{
private static void Main(string[] args)
{
//System.Console.WriteLine($"Main dispatcher: {SynchronizationContext.Current?.GetHashCode()}");
//// 1. Method call - no blocking
//var mainTask = Task.Run(() => DoTheSame());
//mainTask.Wait();
// 2. Anonymous + Thread - no block
//var mainThread = new Thread(
//async () =>
//{
// System.Console.WriteLine($"Before setting dispatcher: {SynchronizationContext.Current?.GetHashCode()}");
// SynchronizationContext.SetSynchronizationContext(
// new DispatcherSynchronizationContext(
// Dispatcher.CurrentDispatcher));
// System.Console.WriteLine($"After setting dispatcher: {SynchronizationContext.Current?.GetHashCode()}");
// var ts = new TaskCompletionSource<bool>();
// await Task.Run(() =>
// {
// ts.SetResult(true);
// });
// await ts.Task;
//});
//mainThread.Start();
//mainThread.Join();
// 3. Anonymous + Task - blocks
var mainTask = Task.Run(
async () =>
{
System.Console.WriteLine($"Before setting dispatcher: {SynchronizationContext.Current?.GetHashCode()}"); // null of course
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
System.Console.WriteLine($"After setting dispatcher: {SynchronizationContext.Current?.GetHashCode()}");
var ts = new TaskCompletionSource<bool>();
await Task.Run(() =>
{
ts.SetResult(true);
});
// using .ConfigureAwait(false); will make it work
await ts.Task;
});
mainTask.Wait();
}
private static async void DoTheSame()
{
System.Console.WriteLine($"Before setting dispatcher: {SynchronizationContext.Current?.GetHashCode()}");
SynchronizationContext.SetSynchronizationContext(
new DispatcherSynchronizationContext(
Dispatcher.CurrentDispatcher));
System.Console.WriteLine($"After setting dispatcher: {SynchronizationContext.Current?.GetHashCode()}");
var ts = new TaskCompletionSource<bool>();
await Task.Run(() =>
{
ts.SetResult(true);
});
await ts.Task;
}
}