using System.Threading.Tasks;
using System.Collections.Concurrent;
public class UISynchronizationContext : SynchronizationContext
private readonly BlockingCollection<(SendOrPostCallback, object)> _queue = new BlockingCollection<(SendOrPostCallback, object)>();
public override void Post(SendOrPostCallback d, object state)
public override void Send(SendOrPostCallback d, object state)
public void RunMessageLoop()
foreach (var (callback, state) in _queue.GetConsumingEnumerable())
public async Task RunMessageLoopAsync()
foreach (var (callback, state) in _queue.GetConsumingEnumerable())
public void StopMessageLoop()
public static T RunSynchronously<T>(Func<Task<T>> callable)
var currentContext = SynchronizationContext.Current;
Console.WriteLine($"RunSynchronously context {currentContext} saved");
SynchronizationContext tempContext = null;
SynchronizationContext.SetSynchronizationContext(tempContext);
Console.WriteLine($"Before callable tid {System.Environment.CurrentManagedThreadId}");
var task = callable().ConfigureAwait(false);
Console.WriteLine($"After callable started tid {System.Environment.CurrentManagedThreadId}");
var result = task.GetAwaiter().GetResult();
Console.WriteLine($"Returning callable result tid {System.Environment.CurrentManagedThreadId}");
Console.WriteLine($"RunSynchronously context {currentContext} restored");
SynchronizationContext.SetSynchronizationContext(currentContext);
public static async Task Delay(int ms){
Console.WriteLine($"Before Delay tid {System.Environment.CurrentManagedThreadId}");
Console.WriteLine($"After Delay tid {System.Environment.CurrentManagedThreadId}");
public static async Task<int> AsyncMethod()
Console.WriteLine($"Before await tid {System.Environment.CurrentManagedThreadId}");
Console.WriteLine($"Await continuation tid {System.Environment.CurrentManagedThreadId}");
public static async Task Main(string[] args)
var uiContext = new UISynchronizationContext();
SynchronizationContext.SetSynchronizationContext(uiContext);
var task = AsyncMethod();
var messageLoopTask = uiContext.RunMessageLoopAsync();
Console.WriteLine($"Async Result: {result}");
Console.WriteLine($"Sync Result: {AsyncHelper.RunSynchronously(AsyncMethod)}");
uiContext.StopMessageLoop();
public static async Task Main2()
var uiContext = new UISynchronizationContext();
SynchronizationContext.SetSynchronizationContext(uiContext);
uiContext.RunMessageLoop();
Console.WriteLine($"Getting the result by awaiting: {await AsyncMethod()} \n###########\n");
int result = AsyncHelper.RunSynchronously(AsyncMethod);
Console.WriteLine($"Result: {result}");
uiContext.StopMessageLoop();