In an ASP.NET 4.5 application, which of these is better for calling an async method from a sync method?
var result = Task.Run(() => SomethingAsync()).GetAwaiter().GetResult(); // or var temp = SynchronizationContext.Current; try { SynchronizationContext.SetSynchronizationContext(null); return SomethingAsync().GetAwaiter().GetResult(); } finally { SynchronizationContext.SetSynchronizationContext(temp); } Note: Yes, I know I should be using async/await all the way down, but I'm asking about the very bottom, and outside of ASP.NET Core the filters and razor views are not async, so if I want to call an async method from a filter or a razor view, I need to sync it some way. Just using SomethingAsync().GetAwaiter().GetResult() leads to a deadlock, because of the SynchronizationContext, so I need a way to run this code without a SynchronizationContext.
EDIT Here is the simple helper class that wraps this up cleanly:
public static class Async { public static T Run<T>(Func<Task<T>> func) { var context = SynchronizationContext.Current; if (context == null) { return func().GetAwaiter().GetResult(); } SynchronizationContext.SetSynchronizationContext(null); try { return func().GetAwaiter().GetResult(); } finally { SynchronizationContext.SetSynchronizationContext(context); } } public static void Run(Func<Task> func) { var context = SynchronizationContext.Current; if (context == null) { func().GetAwaiter().GetResult(); return; } SynchronizationContext.SetSynchronizationContext(null); try { func().GetAwaiter().GetResult(); } finally { SynchronizationContext.SetSynchronizationContext(context); } } } // Example var result = Async.Run(() => GetSomethingAsync("blabla"));
Task.Runapproach is slightly more obviously correct, and theSynchronizationContext.Currentapproach is slightly more performant. Which one is "better" is purely a matter of opinion.ifchecks.SetSynchronizationContext(null)is valid.ifis there is to prevent all the work done inSetSynchronizationContext: dotnetframework.org/default.aspx/DotNET/DotNET/8@0/untmp/…