By Rachel


2011-02-23 18:18:27 8 Comments

I'm learning about async/await, and ran into a situation where I need to call an async method synchronously. How can I do that?

Async method:

public async Task<Customers> GetCustomers()
{
    return await Service.GetCustomersAsync();
}

Normal usage:

public async void GetCustomers()
{
    customerList = await GetCustomers();
}

I've tried using the following:

Task<Customer> task = GetCustomers();
task.Wait()

Task<Customer> task = GetCustomers();
task.RunSynchronously();

Task<Customer> task = GetCustomers();
while(task.Status != TaskStatus.RanToCompletion)

I also tried a suggestion from here, however it doesn't work when the dispatcher is in a suspended state.

public static void WaitWithPumping(this Task task) 
{
        if (task == null) throw new ArgumentNullException(“task”);
        var nestedFrame = new DispatcherFrame();
        task.ContinueWith(_ => nestedFrame.Continue = false);
        Dispatcher.PushFrame(nestedFrame);
        task.Wait();
}

Here is the exception and stack trace from calling RunSynchronously:

System.InvalidOperationException

Message: RunSynchronously may not be called on a task unbound to a delegate.

InnerException: null

Source: mscorlib

StackTrace:

          at System.Threading.Tasks.Task.InternalRunSynchronously(TaskScheduler scheduler)
   at System.Threading.Tasks.Task.RunSynchronously()
   at MyApplication.CustomControls.Controls.MyCustomControl.CreateAvailablePanelList() in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 638
   at MyApplication.CustomControls.Controls.MyCustomControl.get_AvailablePanels() in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 233
   at MyApplication.CustomControls.Controls.MyCustomControl.<CreateOpenPanelList>b__36(DesktopPanel panel) in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 597
   at System.Collections.Generic.List`1.ForEach(Action`1 action)
   at MyApplication.CustomControls.Controls.MyCustomControl.<CreateOpenPanelList>d__3b.MoveNext() in C:\Documents and Settings\...\MyApplication.CustomControls\Controls\MyCustomControl.xaml.cs:line 625
   at System.Runtime.CompilerServices.TaskAwaiter.<>c__DisplayClass7.<TrySetContinuationForAwait>b__1(Object state)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at System.Threading.ExecutionContext.runTryCode(Object userData)
   at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.InvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at MyApplication.App.Main() in C:\Documents and Settings\...\MyApplication\obj\Debug\App.g.cs:line 50
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

24 comments

@Liang 2018-10-24 09:08:51

Tested in .Net 4.6. It also can avoid deadlock.

For async method return Task.

Task DoSomeWork();
Task.Run(async () => await DoSomeWork()).Wait();

For async method return Task<T>

Task<T> GetSomeValue();
var result = Task.Run(() => GetSomeValue()).Result;

Edit:

If the caller is running in the threading pool thread (or the caller is also in a task), it may still cause a dead lock in some situation.

@W92 2019-02-14 13:57:52

My answar after almost 8 years :) The second example - will produce a deadlock in all scheduled context that are mainly used (console app / .NET core / desktop app / ...). here you have more overview what i'm talking about now: medium.com/rubrikkgroup/…

@Curtis 2019-02-06 22:02:41

I have found that SpinWait works pretty well for this.

var task = Task.Run(()=>DoSomethingAsyncronous());

if(!SpinWait.SpinUntil(()=>task.IsComplete, TimeSpan.FromSeconds(30)))
{//Task didn't complete within 30 seconds, fail...
   return false;
}

return true;

The above approach doesn't need to use .Result or .Wait(). It also lets you specify a timeout so that you're not stuck forever in case the task never completes.

@Grax32 2019-04-01 13:08:51

The downvote suggests someone doesn't like this method. Is there someone that can comment on the downside of this?

@Curtis 2019-04-11 22:09:10

In the absence of the downvoter saying WHY the downvote was given, can somebody upvote it? :-)

@Sinatr 2019-05-20 07:59:01

This is polling (spinning), the delegate will be taking thread from pool up to 1000 times per second. It may not return control immediately after task is finished (up to 10+ms error). If finished by timeout the task will continues running, which makes timeout practically useless.

@Curtis 2019-05-22 20:45:43

Actually, I'm using this all over the place in my code and when the condition is met, SpinWaitSpinUntil() immediately exits. So whichever comes first, 'condition met' or timeout, the task exits. It does not continue to run.

@Theo Yaung 2011-02-24 21:29:15

If I am reading your question right - the code that wants the synchronous call to an async method is executing on a suspended dispatcher thread. And you want to actually synchronously block that thread until the async method is completed.

Async methods in C# 5 are powered by effectively chopping the method into pieces under the hood, and returning a Task that can track the overall completion of the whole shabang. However, how the chopped up methods execute can depend on the type of the expression passed to the await operator.

Most of the time, you'll be using await on an expression of type Task. Task's implementation of the await pattern is "smart" in that it defers to the SynchronizationContext, which basically causes the following to happen:

  1. If the thread entering the await is on a Dispatcher or WinForms message loop thread, it ensures that the chunks of the async method occurs as part of the processing of the message queue.
  2. If the thread entering the await is on a thread pool thread, then the remaining chunks of the async method occur anywhere on the thread pool.

That's why you're probably running into problems - the async method implementation is trying to run the rest on the Dispatcher - even though it's suspended.

.... backing up! ....

I have to ask the question, why are you trying to synchronously block on an async method? Doing so would defeat the purpose on why the method wanted to be called asynchronously. In general, when you start using await on a Dispatcher or UI method, you will want to turn your entire UI flow async. For example, if your callstack was something like the following:

  1. [Top] WebRequest.GetResponse()
  2. YourCode.HelperMethod()
  3. YourCode.AnotherMethod()
  4. YourCode.EventHandlerMethod()
  5. [UI Code].Plumbing() - WPF or WinForms Code
  6. [Message Loop] - WPF or WinForms Message Loop

Then once the code has been transformed to use async, you'll typically end up with

  1. [Top] WebRequest.GetResponseAsync()
  2. YourCode.HelperMethodAsync()
  3. YourCode.AnotherMethodAsync()
  4. YourCode.EventHandlerMethodAsync()
  5. [UI Code].Plumbing() - WPF or WinForms Code
  6. [Message Loop] - WPF or WinForms Message Loop

Actually Answering

The AsyncHelpers class above actually works because it behaves like a nested message loop, but it installs its own parallel mechanic to the Dispatcher rather than trying to execute on the Dispatcher itself. That's one workaround for your problem.

Another workaround is to execute your async method on a threadpool thread, and then wait for it to complete. Doing so is easy - you can do it with the following snippet:

var customerList = TaskEx.RunEx(GetCustomers).Result;

The final API will be Task.Run(...), but with the CTP you'll need the Ex suffixes (explanation here).

@Rachel 2011-02-25 14:39:41

+1 for the detailed explanation, however TaskEx.RunEx(GetCustomers).Result hangs the application when it gets run on a suspended dispatcher thread. Also, the GetCustomers() method is normally run async, however in one situation it needs to run synchronously, so I was looking for a way to do that without building a sync version of the method.

@Stephen Cleary 2013-09-05 15:59:50

+1 for "why are you trying to synchronously block on an async method?" There is always a way to properly use async methods; nested loops should certainly be avoided.

@Dan Nguyen 2018-07-27 15:20:06

This is works for me

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    public static class AsyncHelper
    {
        private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);

        public static void RunSync(Func<Task> func)
        {
            _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
        }

        public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        {
            return _myTaskFactory.StartNew(func).Unwrap().GetAwaiter().GetResult();
        }
    }

    class SomeClass
    {
        public async Task<object> LoginAsync(object loginInfo)
        {
            return await Task.FromResult(0);
        }
        public object Login(object loginInfo)
        {
            return AsyncHelper.RunSync(() => LoginAsync(loginInfo));
            //return this.LoginAsync(loginInfo).Result.Content;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var someClass = new SomeClass();

            Console.WriteLine(someClass.Login(1));
            Console.ReadLine();
        }
    }
}

@AK_ 2012-08-02 17:03:47

Be advised this answer is three years old. I wrote it based mostly on a experience with .Net 4.0, and very little with 4.5 especially with async-await. Generally speaking it's a nice simple solution, but it sometimes breaks things. Please read the discussion in the comments.

.Net 4.5

Just use this:

// For Task<T>: will block until the task is completed...
var result = task.Result; 

// For Task (not Task<T>): will block until the task is completed...
task2.RunSynchronously();

See: TaskAwaiter, Task.Result, Task.RunSynchronously


.Net 4.0

Use this:

var x = (IAsyncResult)task;
task.Start();

x.AsyncWaitHandle.WaitOne();

...or this:

task.Start();
task.Wait();

@class 2013-07-24 00:00:01

If you want to use async in .NET 4.0 you can install the NuGet package async: nuget.org/packages/Microsoft.Bcl.Async

@Jordy Langen 2013-08-22 19:17:39

.Result can produce a deadlock in certain scenario's

@AK_ 2013-08-29 13:58:55

@JordyLangen of course, you are waiting for that task to complete... But that's usual with parallel programming, and always true when waiting on something...

@Stephen Cleary 2013-09-05 15:58:19

Result can easily cause deadlock in async code, as I describe on my blog.

@AK_ 2013-10-15 16:36:46

@StephenCleary I read your post, and tried it myself. I honestly think someone at microsoft was really drunk... It's the same issue as like winforms and background threads....

@Cortlendt 2014-02-28 06:38:07

task.Wait() sometimes does not work "synchronously". This introduces some very nasty bugs

@sgnsajgon 2014-09-13 10:02:04

The question concerns a Task that is returned by async method. Such kind of Task may have already been started, executed, or canceled, so usage of Task.RunSynchronously method may result in InvalidOperationException. See MSDN page: Task.RunSynchronously Method. Besides, that Task is probably created by Task.Factory.StartNew or Task.Run methods (inside async method), so it's dangerous to try start it again. Some race conditions may occur at runtime. In the othe hand, Task.Wait and Task.Result may result i deadlock.

@JonnyRaa 2014-09-25 11:17:45

Run Synchronously worked for me... I don't know if I'm missing something but this seems preferable to the horrors of the marked answer - I was just looking for a way of switching off async for testing code that just there to stop the ui from hanging

@Justin Skiles 2015-03-04 03:09:55

Result causes weird connection exceptions in Entity Framework

@Mohammad Chamanpara 2015-08-16 13:34:01

When you run this the following error occurs : RunSynchronously may not be called on a task not bound to a delegate, such as the task returned from an asynchronous method.

@pants 2017-09-26 15:09:48

The documentation for RunSynchronously() suggests calling Wait() afterword "to handle any exceptions that the task might throw".

@S.Serpooshan 2019-03-12 05:57:14

It worth to mention that based on this and this, the deadlock is not a problem for ASP.NET Core!

@David Burg 2019-06-25 04:58:07

a. RunSynchronously may not be called on a task not bound to a delegate so I wrapped it in a Task(async () => await methodAsync().ConfigureAwait(continueOnCapturedContext: false)) b. Added the .Wait() per the MSDN article Surprise the task started synchronous execution then claimed completion when I/O started, leading to baffling race condition. Fell back to .GetAwaiter().GetResult(); which really waited for completion. By why is RunSynchronously() and Wait() returning before async task is really done???

@Rachel 2011-02-23 21:02:36

Here's a workaround I found that works for all cases (including suspended dispatchers). It's not my code and I'm still working to fully understand it, but it does work.

It can be called using:

customerList = AsyncHelpers.RunSync<List<Customer>>(() => GetCustomers());

Code is from here

public static class AsyncHelpers
{
    /// <summary>
    /// Execute's an async Task<T> method which has a void return value synchronously
    /// </summary>
    /// <param name="task">Task<T> method to execute</param>
    public static void RunSync(Func<Task> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        synch.Post(async _ =>
        {
            try
            {
                await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();

        SynchronizationContext.SetSynchronizationContext(oldContext);
    }

    /// <summary>
    /// Execute's an async Task<T> method which has a T return type synchronously
    /// </summary>
    /// <typeparam name="T">Return Type</typeparam>
    /// <param name="task">Task<T> method to execute</param>
    /// <returns></returns>
    public static T RunSync<T>(Func<Task<T>> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        T ret = default(T);
        synch.Post(async _ =>
        {
            try
            {
                ret = await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();
        SynchronizationContext.SetSynchronizationContext(oldContext);
        return ret;
    }

    private class ExclusiveSynchronizationContext : SynchronizationContext
    {
        private bool done;
        public Exception InnerException { get; set; }
        readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false);
        readonly Queue<Tuple<SendOrPostCallback, object>> items =
            new Queue<Tuple<SendOrPostCallback, object>>();

        public override void Send(SendOrPostCallback d, object state)
        {
            throw new NotSupportedException("We cannot send to our same thread");
        }

        public override void Post(SendOrPostCallback d, object state)
        {
            lock (items)
            {
                items.Enqueue(Tuple.Create(d, state));
            }
            workItemsWaiting.Set();
        }

        public void EndMessageLoop()
        {
            Post(_ => done = true, null);
        }

        public void BeginMessageLoop()
        {
            while (!done)
            {
                Tuple<SendOrPostCallback, object> task = null;
                lock (items)
                {
                    if (items.Count > 0)
                    {
                        task = items.Dequeue();
                    }
                }
                if (task != null)
                {
                    task.Item1(task.Item2);
                    if (InnerException != null) // the method threw an exeption
                    {
                        throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
                    }
                }
                else
                {
                    workItemsWaiting.WaitOne();
                }
            }
        }

        public override SynchronizationContext CreateCopy()
        {
            return this;
        }
    }
}

@Cameron MacFarland 2013-02-08 16:29:56

For some background on how this works, Stephen Toub (Mr Parallel) wrote a series of posts about this. Part 1 Part 2 Part 3

@Tom Jacques 2013-06-25 19:47:03

I updated John's code to work without wrapping tasks in lambdas: github.com/tejacques/AsyncBridge. Essentially you work with async blocks with the using statement. Anything inside a using block happens asynchronously, with a wait at the end. The downside is that you need to unwrap the task yourself in a callback, but it's still fairly elegant, especially if you need to call several async functions at once.

@ghord 2013-07-11 11:12:15

This method blocks the UI thread it is executed on. Would it be possible to somehow use Dispatcher.PushFrame(DispatcherFrame) method to prevent blocking the UI?

@Mike Marynowski 2013-07-15 17:39:22

@ghord - if you don't want to block the UI then you can't run it synchronously...by definition it will block the thread it runs on. Just await it if you don't want it to block. I don't understand the point of what you are asking.

@ghord 2013-07-15 20:01:15

@MikeMarynowski I had a problem with async void (cannot change to Task) method with awaits, which I wanted to execute fully before passing control. This solution helps, but it hangs the UI thread, which I was trying to avoid.

@Mike Marynowski 2013-07-16 00:14:53

What you are asking for is impossible though, just think about it - if you don't pass control back to the UI thread then the UI won't update. By definition, something running synchronously on the UI thread will freeze the UI until it finishes. I'm certain there's a better way to achieve whatever it is you are trying to do. Instead of bloating this thread more, how about you post a separate question and I will try my best to answer it.

@ghord 2013-07-17 17:10:05

@MikeMarynowski It was possible in 4.0 with Dispatcher.PushFrame and it worked quite well. It just so happens it causes async/await code to deadlock. I don't need new question - I just reorganized my app so it didn't need this.

@justin.lovell 2014-01-23 06:56:18

@StephenCleary Although I generally agree with you that the code should be async all the way down, sometimes you find yourself in an infeasible situation where one has to force it as a synchronous call. Basically, my situation is that all my data access code is in async fashion. I needed to build a sitemap based on the sitemap and the third party library I was using was MvcSitemap. Now when one is extending it via the DynamicNodeProviderBase base class, one cannot declare it as a async method. Either I had to replace with a new library, or just call a synchronous op.

@Stephen Cleary 2014-01-23 12:33:46

@justin.lovell: Yes, library limitations can force us to put in hacks, at least until the library is updated. It sounds like MvcSitemap is one such situation where a hack is required (MVC filters and child actions, too); I just dissuade people from this in general because hacks like this are used way too often when they are not necessary. With MVC in particular, some ASP.NET/MVC APIs do assume that they have an AspNetSynchronizationContext, so this particular hack won't work if you're calling those APIs.

@Ivan Danilov 2015-10-18 23:47:18

@ghord sure, it still works perfectly: gist.github.com/ivan-danilov/3ee430522d596ccf6496

@ZunTzu 2015-10-27 18:30:22

This code will not work. If it is called from a pool thread it can trigger thread-starvation deadlock. Your caller will block waiting for the operation to complete, which may never happen if he has exhausted the thread pool. See this article.

@Rachel 2016-07-07 15:00:59

@Paval This answer is pretty old, however in the past I never had any problems like that with the code. The use of the await keyword says "queue this command on a separate thread, and everything below this to run upon thread completion, then end this code block and go back to whatever else you were doing", which in this case is the message loop calling .WaitOne repeatedly. Because the task runs on a separate thread, I don't think you should experiencing any dead locks with this code.

@Sentinel 2016-09-08 13:18:33

Sometimes you inherit someone else's code that was written all sync, and you have to deliver something by a certain deadline, and rewriting everything to be async upwards isn't an option.

@Michael Kropat 2016-10-05 17:27:17

This code has a bug. It doesn't restore the old context (SynchronizationContext.SetSynchronizationContext(oldContext‌​)) when an exception is thrown. Using try { ... } finally { ... } fixes it.

@mqueirozcorreia 2016-11-04 23:04:13

To avoid FxCopy warning Implement IDisposable in ExclusiveSynchronizationContext, disposing _workItemsWaiting

@Alexander Puchkov 2017-01-20 16:34:17

@MichaelKropat can you post your version? It is also getting stuck for me when exception is thrown in async method.

@Melvyn 2018-02-21 08:40:47

Unfortunately it does not work for all cases. WaitOne() internally pumps messages (so that COM things work as expected I believe). This means that external code (such as event handlers) can execute every time a task is awaited in the custom context, and WaitOne() is called. I experienced such a situation causing a deadlock between the main thread and itself :/ I solved it by executing my task on a new thread, and actually blocking with a while (!task.IsCompleted) { /*wait*/}. This is ugly, but unless something in your task tries to execute on the waiting thread, everything should work.

@Vivek 2018-04-03 09:10:06

Is there any advantage to this code against Task.Run() ??

@James Ko 2016-02-07 19:29:54

Surprised no one mentioned this:

public Task<int> BlahAsync()
{
    // ...
}

int result = BlahAsync().GetAwaiter().GetResult();

Not as pretty as some of the other methods here, but it has the following benefits:

  • it doesn't swallow exceptions (like Wait)
  • it won't wrap any exceptions thrown in an AggregateException (like Result)
  • works for both Task and Task<T> (try it out yourself!)

Also, since GetAwaiter is duck-typed, this should work for any object that is returned from an async method (like ConfiguredAwaitable or YieldAwaitable), not just Tasks.


edit: Please note that it's possible for this approach (or using .Result) to deadlock, unless you make sure to add .ConfigureAwait(false) every time you await, for all async methods that can possibly be reached from BlahAsync() (not just ones it calls directly). Explanation.

// In BlahAsync() body
await FooAsync(); // BAD!
await FooAsync().ConfigureAwait(false); // Good... but make sure FooAsync() and
                                        // all its descendants use ConfigureAwait(false)
                                        // too. Then you can be sure that
                                        // BlahAsync().GetAwaiter().GetResult()
                                        // won't deadlock.

If you're too lazy to add .ConfigureAwait(false) everywhere, and you don't care about performance you can alternatively do

Task.Run(() => BlahAsync()).GetAwaiter().GetResult()

@Lee McPherson 2016-04-07 05:22:56

Works for me for simple stuff. Also, if the method returns an IAsyncOperation, I had to convert it to a Task first: BlahAsync().AsTask().GetAwaiter().GetResult();

@Augusto Barreto 2017-12-13 14:30:01

This caused a deadlock inside an asmx web method. Nevertheless, wrapping the method call in a Task.Run() made it work: Task.Run(() => BlahAsync()).GetAwaiter().GetResult()

@dythim 2018-01-30 02:19:34

I like this approach best syntactically because it does not involve lambdas.

@Rachel 2018-03-01 21:48:53

Please do NOT edit other people's answers to insert a link to your own. If you believe your answer is better, leave it as a comment instead.

@Ghen 2018-03-26 01:48:39

Should be a solution for the question as it addresses the problem, minimal custom code, and answer perfectly explains key points.

@Theophilus 2019-09-04 17:04:45

docs.microsoft.com/en-us/dotnet/api/… says about GetAwaiter(), "This method is intended for compiler user rather than use directly in code."

@Ogglas 2017-09-25 13:49:42

Simply calling .Result; or .Wait() is a risk for deadlocks as many have said in comments. Since most of us like oneliners you can use these for .Net 4.5<

Acquiring a value via an async method:

var result = Task.Run(() => asyncGetValue()).Result;

Syncronously calling an async method

Task.Run(() => asyncMethod()).Wait();

No deadlock issues will occur due to the use of Task.Run.

Source:

https://stackoverflow.com/a/32429753/3850405

@pixel 2016-10-25 23:22:45

The simplest way I have found to run task synchronously and without blocking UI thread is to use RunSynchronously() like:

Task t = new Task(() => 
{ 
   //.... YOUR CODE ....
});
t.RunSynchronously();

In my case, I have an event that fires when something occurs. I dont know how many times it will occur. So, I use code above in my event, so whenever it fires, it creates a task. Tasks are executed synchronously and it works great for me. I was just surprised that it took me so long to find out of this considering how simple it is. Usually, recommendations are much more complex and error prone. This was it is simple and clean.

@S.Serpooshan 2018-09-10 09:07:39

But how could we use this method when the async code returns something we need?

@Mahesh 2016-10-19 04:13:30

use below code snip

Task.WaitAll(Task.Run(async () => await service.myAsyncMethod()));

@gandhraj gayakwad 2015-09-03 07:39:35

Try following code it works for me:

public async void TaskSearchOnTaskList (SearchModel searchModel)
{
    try
    {
        List<EventsTasksModel> taskSearchList = await Task.Run(
            () => MakeasyncSearchRequest(searchModel),
            cancelTaskSearchToken.Token);

        if (cancelTaskSearchToken.IsCancellationRequested
                || string.IsNullOrEmpty(rid_agendaview_search_eventsbox.Text))
        {
            return;
        }

        if (taskSearchList == null || taskSearchList[0].result == Constants.ZERO)
        {
            RunOnUiThread(() => {
                textViewNoMembers.Visibility = ViewStates.Visible;                  
                taskListView.Visibility = ViewStates.Gone;
            });

            taskSearchRecureList = null;

            return;
        }
        else
        {
            taskSearchRecureList = TaskFooterServiceLayer
                                       .GetRecurringEvent(taskSearchList);

            this.SetOnAdapter(taskSearchRecureList);
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine("ActivityTaskFooter -> TaskSearchOnTaskList:" + ex.Message);
    }
}

@Stephen Cleary 2016-09-07 13:40:33

I'm learning about async/await, and ran into a situation where I need to call an async method synchronously. How can I do that?

The best answer is you don't, with the details dependent on what the "situation" is.

Is it a property getter/setter? In most cases, it's better to have asynchronous methods than "asynchronous properties". (For more info, see my blog post on asynchronous properties).

Is this an MVVM app and you want to do asynchronous data binding? Then use something like my NotifyTask, as described in my MSDN article on asynchronous data binding.

Is it a constructor? Then you probably want to consider an asynchronous factory method. (For more info, see my blog post on asynchronous constructors).

There's almost always a better answer than to do sync-over-async.

If it's not possible for your situation (and you know this by asking a question here describing the situation), then I'd recommend just using synchronous code. Async all the way is best; sync all the way is second-best. Sync-over-async is not recommended.

However, there are a handful of situations where sync-over-async is necessary. Specifically, you are constrained by the calling code so that you have to be sync (and have absolutely no way to re-think or re-structure your code to allow asynchrony), and you have to call async code. This is a very rare situation, but it does come up from time to time.

In that case, you would need to use one of the hacks described in my article on brownfield async development, specifically:

  • Blocking (e.g., GetAwaiter().GetResult()). Note that this can cause deadlocks (as I describe on my blog).
  • Running the code on a thread pool thread (e.g., Task.Run(..).GetAwaiter().GetResult()). Note that this will only work if the asynchronous code can be run on a thread pool thread (i.e., is not dependent on a UI or ASP.NET context).
  • Nested message loops. Note that this will only work if the asynchronous code only assumes a single-threaded context, not a specific context type (a lot of UI and ASP.NET code expect a specific context).

Nested message loops are the most dangerous of all the hacks, because it causes re-entrancy. Re-entrancy is extremely tricky to reason about, and (IMO) is the cause of most application bugs on Windows. In particular, if you're on the UI thread and you block on a work queue (waiting for the async work to complete), then the CLR actually does some message pumping for you - it'll actually handle some Win32 messages from within your code. Oh, and you have no idea which messages - when Chris Brumme says "Wouldn’t it be great to know exactly what will get pumped? Unfortunately, pumping is a black art which is beyond mortal comprehension.", then we really have no hope of knowing.

So, when you block like this on a UI thread, you're asking for trouble. Another cbrumme quote from the same article: "From time to time, customers inside or outside the company discover that we are pumping messages during managed blocking on an STA [UI thread]. This is a legitimate concern, because they know that it’s very hard to write code that’s robust in the face of reentrancy."

Yes, it is. Very hard to write code that's robust in the face of reentrancy. And nested message loops force you to write code that's robust in the face of reentrancy. This is why the accepted (and most-upvoted) answer for this question is extremely dangerous in practice.

If you are completely out of all other options - you can't redesign your code, you can't restructure it to be async - you are forced by unchangeable calling code to be sync - you can't change the downstream code to be sync - you can't block - you can't run the async code on a separate thread - then and only then should you consider embracing reentrancy.

If you do find yourself in this corner, I would recommend using something like Dispatcher.PushFrame for WPF apps, looping with Application.DoEvents for WinForm apps, and for the general case, my own AsyncContext.Run.

@Alexei Levenkov 2017-02-05 08:05:09

Stephen, there is another very similar qestion which you provided awesome answer too. Do you think one of them can be closed as duplicate or maybe merge request or bring up on meta first (as each q has ~200K views 200+ votes)? Suggestions?

@Stephen Cleary 2017-02-05 14:15:19

@AlexeiLevenkov: I don't feel right doing that, for a few reasons: 1) The answer on the linked question is fairly out-of-date. 2) I've written an entire article on the subject that I feel is more complete than any existing SO Q/A. 3) The accepted answer on this question is extremely popular. 4) I am vehemently opposed to that accepted answer. So, closing this as a dup of that would be an abuse of power; closing that as a dup of this (or merging) would empower a dangerous answer even more. I let it be, and leave it to the community.

@Alexei Levenkov 2017-02-06 18:14:52

Ok. I'll consider bringing it up on meta than in some way.

@Mark Amery 2017-06-13 13:20:44

This answer goes a long way over my head. "Use async all the way down" is confusing advice, due to clearly not being possible to follow. A program with an async Main() method doesn't compile; at some point you've got to bridge the gap between the sync and async worlds. It's not a "very rare situation", it's necessary in literally every program that calls an async method. There is no option to not "do sync-over-async", just an option to shunt that burden up to the calling method instead of shouldering it in the one you're currently writing.

@Stephen Cleary 2017-06-13 14:41:20

@MarkAmery: Sync-over-async is necessary in the Main method of console apps. ASP.NET, unit test frameworks, and every UI system all support async natively. Even if all your apps are console apps, you'd only need to do sync-over-async once per app. (of course, library callbacks that don't support async yet may require additional hacks).

@ygoe 2017-12-13 16:53:05

Great. I'm about to put async on all of the methods in my application now. And that's a lot. Can't this just be the default?

@S.Serpooshan 2019-03-12 05:54:31

It worth to mention that as you replied me and based on your blog here, the deadlock is not a problem for ASP.NET Core!

@user2057962 2016-03-08 23:21:17

Or you could just go with:

customerList = Task.Run<List<Customer>>(() => { return GetCustomers(); }).Result;

For this to compile make sure you reference extension assembly:

System.Net.Http.Formatting

@donttellya 2016-02-16 09:58:37

I think the following helper method could also solve the problem.

private TResult InvokeAsyncFuncSynchronously<TResult>(Func< Task<TResult>> func)
    {
        TResult result = default(TResult);
        var autoResetEvent = new AutoResetEvent(false);

        Task.Run(async () =>
        {
            try
            {
                result = await func();
            }
            catch (Exception exc)
            {
                mErrorLogger.LogError(exc.ToString());
            }
            finally
            {
                autoResetEvent.Set();
            }
        });
        autoResetEvent.WaitOne();

        return result;
    }

Can be used the following way:

InvokeAsyncFuncSynchronously(Service.GetCustomersAsync);

@donttellya 2016-03-21 08:22:49

Please explain the voting

@donttellya 2016-04-22 08:18:59

...I am still eagerly interested why this answer was down voted?

@tmt 2016-05-18 14:02:34

It is not an true "synchronously".Y ou create two threads and wait in first results of other.

@Dan Pantry 2016-09-13 10:22:42

and all things aside, this is a very bad idea.

@tmrog 2017-06-20 12:12:29

I just wrote almost the identical code (line by line the same) but instead using SemaphoreSlim instead of the auto reset event. Wish I had seen this sooner. I find this approach to prevent deadlocks and keeps your async code running the same as it does in true asynchronous scenarios. Not really sure why this is a bad idea. Seems much cleaner than the other approaches I have seen above.

@tmrog 2017-06-20 12:32:15

@DanPantry I am actually seeing some deadlocks now with this approach that I don't understand. Could you expand on why it is a bad idea?

@tmrog 2017-06-20 13:20:08

My bad. I got. this working now. My problem was that I was creating the task on the main thread and then passed that task to the invoke async method. Thanks @donttellya your code helped me out.

@RredCat 2012-06-20 22:10:20

Just a little note - this approach:

Task<Customer> task = GetCustomers();
task.Wait()

works for WinRT.

Let me explain:

private void TestMethod()
{
    Task<Customer> task = GetCustomers(); // call async method as sync and get task as result
    task.Wait(); // wait executing the method
    var customer = task.Result; // get's result.
    Debug.WriteLine(customer.Name); //print customer name
}
public class Customer
{
    public Customer()
    {
        new ManualResetEvent(false).WaitOne(TimeSpan.FromSeconds(5));//wait 5 second (long term operation)
    }
    public string Name { get; set; }
}
private Task<Customer> GetCustomers()
{
    return Task.Run(() => new Customer
    {
        Name = "MyName"
    });
}

Moreover this approach works for Windows Store solutions only!

Note: This way isn't thread safe if you call your method inside of other async method (according to comments of @Servy)

@RredCat 2013-12-16 19:01:53

I explained this solution, check EDIT section.

@Servy 2013-12-16 19:07:32

This can very easily result in deadlocks when called in asynchronous situations.

@RredCat 2013-12-16 20:49:18

@Servy make sense. So as I get correct using Wait(timeOut) can help, right?

@Servy 2013-12-16 20:50:48

Then you need to worry about having the timeout being reached when the operation isn't actually done, which is very bad, and also the time spent waiting until the timeout in the cases where it deadlocks (and in that case you're still continuing on when it's not done). So no, that doesn't fix the problem.

@RredCat 2013-12-16 21:41:11

@Servy Looks like I have to implement CancellationToken for my solution.

@RredCat 2013-12-16 21:47:18

@Servy Why, could you explain a bit?

@Servy 2013-12-16 21:49:50

I could, or you could just ask Google about it, or for that matter just look at the comments on the answers that are, more or less, a duplicate of yours; in particular the one with the most votes, as it has [a link to] an explanation.

@sgnsajgon 2014-09-13 10:33:18

Your example works because your GetCustomers() method is not the async method in terms of C# 5.0 (no async-await keywords pair), but just a Task-returning method. The question was about C# 5.0 async method. Mark your GetCustomers() method as async, then await Task.Run() invocation, then you will probably get deadlock.

@wenhx 2014-12-02 02:06:48

I found this code at Microsoft.AspNet.Identity.Core component, and it works.

private static readonly TaskFactory _myTaskFactory = new 
     TaskFactory(CancellationToken.None, TaskCreationOptions.None, 
     TaskContinuationOptions.None, TaskScheduler.Default);

// Microsoft.AspNet.Identity.AsyncHelper
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
    CultureInfo cultureUi = CultureInfo.CurrentUICulture;
    CultureInfo culture = CultureInfo.CurrentCulture;
    return AsyncHelper._myTaskFactory.StartNew<Task<TResult>>(delegate
    {
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = cultureUi;
        return func();
    }).Unwrap<TResult>().GetAwaiter().GetResult();
}

@Contango 2014-09-12 17:41:19

This answer is designed for anyone who is using WPF for .NET 4.5.

If you attempt to execute Task.Run() on the GUI thread, then task.Wait() will hang indefinitely, if you do not have the async keyword in your function definition.

This extension method solves the problem by checking to see if we are on the GUI thread, and if so, running the task on the WPF dispatcher thread.

This class can act as the glue between the async/await world and the non-async/await world, in situations where it is unavoidable, such as MVVM properties or dependencies on other APIs that do not use async/await.

/// <summary>
///     Intent: runs an async/await task synchronously. Designed for use with WPF.
///     Normally, under WPF, if task.Wait() is executed on the GUI thread without async
///     in the function signature, it will hang with a threading deadlock, this class 
///     solves that problem.
/// </summary>
public static class TaskHelper
{
    public static void MyRunTaskSynchronously(this Task task)
    {
        if (MyIfWpfDispatcherThread)
        {
            var result = Dispatcher.CurrentDispatcher.InvokeAsync(async () => { await task; });
            result.Wait();
            if (result.Status != DispatcherOperationStatus.Completed)
            {
                throw new Exception("Error E99213. Task did not run to completion.");
            }
        }
        else
        {
            task.Wait();
            if (task.Status != TaskStatus.RanToCompletion)
            {
                throw new Exception("Error E33213. Task did not run to completion.");
            }
        }
    }

    public static T MyRunTaskSynchronously<T>(this Task<T> task)
    {       
        if (MyIfWpfDispatcherThread)
        {
            T res = default(T);
            var result = Dispatcher.CurrentDispatcher.InvokeAsync(async () => { res = await task; });
            result.Wait();
            if (result.Status != DispatcherOperationStatus.Completed)
            {
                throw new Exception("Error E89213. Task did not run to completion.");
            }
            return res;
        }
        else
        {
            T res = default(T);
            var result = Task.Run(async () => res = await task);
            result.Wait();
            if (result.Status != TaskStatus.RanToCompletion)
            {
                throw new Exception("Error E12823. Task did not run to completion.");
            }
            return res;
        }
    }

    /// <summary>
    ///     If the task is running on the WPF dispatcher thread.
    /// </summary>
    public static bool MyIfWpfDispatcherThread
    {
        get
        {
            return Application.Current.Dispatcher.CheckAccess();
        }
    }
}

@Clement 2014-07-23 05:42:37

This is working well for me

public static class TaskHelper
{
    public static void RunTaskSynchronously(this Task t)
    {
        var task = Task.Run(async () => await t);
        task.Wait();
    }

    public static T RunTaskSynchronously<T>(this Task<T> t)
    {
        T res = default(T);
        var task = Task.Run(async () => res = await t);
        task.Wait();
        return res;
    }
}

@sgnsajgon 2014-09-15 18:45:39

You need to also use Task.Unwrap method, because your Task.Wait statement causes waiting for outer Task (created by Task.Run), not for inner await t Task passed as parameter of extension method. Your Task.Run method returns not Task<T>, but Task<Task<T>>. In some simple scenarios your solution may works because of TaskScheduler optimizations, for example using TryExecuteTaskInline method to execute Tasks within current thread during Wait operation .Please look at my comment to this answer.

@Clement 2014-09-15 23:02:44

That is not correct. The Task.Run will return Task<T>. See this overload msdn.microsoft.com/en-us/library/hh194918(v=vs.110).aspx

@ygoe 2016-09-26 15:20:36

How is this supposed to be used? This deadlocks in WPF: MyAsyncMethod().RunTaskSynchronously();

@J. Lennon 2013-10-05 02:54:50

I've faced it a few times, mostly in unit testing or in a windows service development. Currently I always use this feature:

        var runSync = Task.Factory.StartNew(new Func<Task>(async () =>
        {
            Trace.WriteLine("Task runSync Start");
            await TaskEx.Delay(2000); // Simulates a method that returns a task and
                                      // inside it is possible that there
                                      // async keywords or anothers tasks
            Trace.WriteLine("Task runSync Completed");
        })).Unwrap();
        Trace.WriteLine("Before runSync Wait");
        runSync.Wait();
        Trace.WriteLine("After runSync Waited");

It's simple, easy and I had no problems.

@AndreFeijo 2017-02-16 21:52:50

This is the only one that didn't deadlock for me.

@Dan Abramov 2011-02-23 18:23:15

In your code, your first wait for task to execute but you haven't started it so it waits indefinitely. Try this:

Task<Customer> task = GetCustomers();
task.RunSynchronously();

Edit:

You say that you get an exception. Please post more details, including stack trace.
Mono contains the following test case:

[Test]
public void ExecuteSynchronouslyTest ()
{
        var val = 0;
        Task t = new Task (() => { Thread.Sleep (100); val = 1; });
        t.RunSynchronously ();

        Assert.AreEqual (1, val);
}

Check if this works for you. If it does not, though very unlikely, you might have some odd build of Async CTP. If it does work, you might want to examine what exactly the compiler generates and how Task instantiation is different from this sample.

Edit #2:

I checked with Reflector that the exception you described occurs when m_action is null. This is kinda odd, but I'm no expert on Async CTP. As I said, you should decompile your code and see how exactly Task is being instantiated any how come its m_action is null.


P.S. What's the deal with the occasional downvotes? Care to elaborate?

@Rachel 2011-02-23 18:51:48

I adjusted my question to make the code I had attempted a bit clearer. RunSynchronously returns an error of RunSynchronously may not be called on a task unbound to a delegate. Google is no help since all the results for that are in chinese...

@Rachel 2011-02-23 19:40:52

I think the difference is that I don't create the Task and then try to run it. Instead, the task is created by the async method when the await keyword is used. The exception posted in my earlier comment is the exception I get, although it is one of the few that I cannot Google and find a cause or resolution for.

@Dan Abramov 2011-02-23 19:44:56

async and async keywords are nothing more than syntax sugar. Compiler generates code to create Task<Customer> in GetCustomers() so that's where I would look first. As for exception, you only posted exception message, which is useless without exception type and stack trace. Call exception's ToString() method and post output in the question.

@Rachel 2011-02-23 20:00:51

@gaearon: I posted the exception details and stack trace in my original question.

@Dan Abramov 2011-02-23 20:27:18

I'm also wondering if you're using Task from .NET 4.0 (not some preview release) and stable version of Async CTP.

@Rachel 2011-02-23 20:59:06

I'm using the most stable release of AsyncCTP as of a month or two ago, and the .Net 4.0 Task object. I actually found an alternative that works, although its not my code so I'm still working to fully understand it.

@Dan Abramov 2011-02-23 21:04:03

OK, please post it later as your own answer so others can benefit. Thanks!

@Rachel 2011-02-24 13:03:20

@gaearon: Workaround posted below

@sgnsajgon 2014-09-15 19:01:23

@gaearon I think you had got downvotes because your post is not applicable to question. The discussion is about async-await methods, not about simple Task-returning methods. Moreover, in my opinion, async-await mechanism is a syntax sugar, but not so trivial - there is continuation , context capturing, local context resuming, enhanced local exceptions handling, and more. Then, you shouldn't invoke RunSynchronously method on result of the async method, because by definition asynchronous method should return Task that is currently at least scheduled, and more than once is in the running state.

@Dan Abramov 2014-09-16 06:35:48

@sgnsajgon: Agreed!

@ksemenenko 2013-09-27 20:29:16

    private int GetSync()
    {
        try
        {
            ManualResetEvent mre = new ManualResetEvent(false);
            int result = null;

            Parallel.Invoke(async () =>
            {
                result = await SomeCalcAsync(5+5);
                mre.Set();
            });

            mre.WaitOne();
            return result;
        }
        catch (Exception)
        {
            return null;
        }
    }

@Michael L Perry 2013-06-13 18:50:54

It's much simpler to run the task on the thread pool, rather than trying to trick the scheduler to run it synchronously. That way you can be sure that it won't deadlock. Performance is affected because of the context switch.

Task<MyResult> DoSomethingAsync() { ... }

// Starts the asynchronous task on a thread-pool thread.
// Returns a proxy to the original task.
Task<MyResult> task = Task.Run(() => DoSomethingAsync());

// Will block until the task is completed...
MyResult result = task.Result; 

@J. Lennon 2013-10-06 23:17:30

And if the task is void (without result)?

@Michael L Perry 2014-04-09 14:51:23

Then you call task.Wait(). The data type is simply Task.

@sgnsajgon 2014-09-13 09:33:46

Let's assume that DoSomethingAsync() is long-running async method as whole (internally it awaits a long-running task), but it yields back a flow control to its caller quickly, thus the lambda argument work ends also quickly. The result of Tusk.Run() may Task<Task> or Task<Task<>>, so you are awaiting a result of outer task which is completed quickly, but inner task ( due to awaiting long-running job in async method) is still running. Conclusions are that we probably need to use Unwrap() approach (as was done in @J.Lennon post) to achieve synchronous behaviour of async method.

@ZunTzu 2015-11-02 09:36:34

@sgnsajgon You are wrong. Task.Run is different than Task.Factory.StartNew in that it automatically unwraps the result already. See this article.

@ygoe 2017-12-13 16:36:21

Can I just write Task.Run(DoSomethingAsync) instead? This removes one level of delegates.

@Michael L Perry 2018-02-20 22:17:08

Yep. Going the opposite direction, though, as in Task<MyResult> task = Task.Run(async () => await DoSomethingAsync()); is more explicit and addresses the concern by @sgnsajgon that it might be returning a Task<Task<MyResult>>. The correct overload of Task.Run is selected either way, but the async delegate makes your intent obvious.

@user2113284 2013-02-26 23:13:36

On wp8:

Wrap it:

Task GetCustomersSynchronously()
{
    Task t = new Task(async () =>
    {
        myCustomers = await GetCustomers();
    }
    t.RunSynchronously();
}

Call it:

GetCustomersSynchronously();

@Rico Suter 2013-07-29 11:09:04

Nope, this wont work, because the task does not await the delegate from the constructor (its a delegate and not a task..)

@Daniel A. White 2011-02-23 18:20:34

Why not create a call like:

Service.GetCustomers();

that isn't async.

@Rachel 2011-02-23 18:49:01

That's going to be what I do if I can't get this working... create a Sync version in addition to an Async version

Related Questions

Sponsored Content

2 Answered Questions

[SOLVED] NullReference Exception in PresentationFramework

  • 2016-05-23 14:49:31
  • marczellm
  • 732 View
  • 1 Score
  • 2 Answer
  • Tags:   c# .net wpf

1 Answered Questions

2 Answered Questions

[SOLVED] How to debug binding in WPF

0 Answered Questions

Multiple opening and closing of modules using Prism crashes application

0 Answered Questions

Shared Memory Key Overflow

  • 2014-06-13 12:57:25
  • bl4kh4k
  • 211 View
  • 1 Score
  • 0 Answer
  • Tags:   c#

2 Answered Questions

[SOLVED] Loading dll from resources fails

  • 2012-09-21 11:54:07
  • Andrzej Gis
  • 1818 View
  • 0 Score
  • 2 Answer
  • Tags:   c# wpf

2 Answered Questions

[SOLVED] an Interesting Exception While get an Image from Internet

0 Answered Questions

InvalidOperationException is thrown when a ribbon is clicked

2 Answered Questions

Sponsored Content