How to call asynchronous method from synchronous method in C#?

async-await, asynchronous, c#, synchronous

Solution

Asynchronous programming does "grow" through the code base. It has been compared to a zombie virus. The best solution is to allow it to grow, but sometimes that's not possible.

I have written a few types in my Nito.AsyncEx library for dealing with a partially-asynchronous code base. There's no solution that works in every situation, though.

Solution A

If you have a simple asynchronous method that doesn't need to synchronize back to its context, then you can use `Task.WaitAndUnwrapException`:

var task = MyAsyncMethod();
var result = task.WaitAndUnwrapException();

You do not want to use `Task.Wait` or `Task.Result` because they wrap exceptions in `AggregateException`.

This solution is only appropriate if `MyAsyncMethod` does not synchronize back to its context. In other words, every `await` in `MyAsyncMethod` should end with `ConfigureAwait(false)`. This means it can't update any UI elements or access the ASP.NET request context.

Solution B

If `MyAsyncMethod` does need to synchronize back to its context, then you may be able to use `AsyncContext.RunTask` to provide a nested context:

var result = AsyncContext.RunTask(MyAsyncMethod).Result;

*Update 4/14/2014: In more recent versions of the library the API is as follows:

var result = AsyncContext.Run(MyAsyncMethod);

(It's OK to use `Task.Result` in this example because `RunTask` will propagate `Task` exceptions).

The reason you may need `AsyncContext.RunTask` instead of `Task.WaitAndUnwrapException` is because of a rather subtle deadlock possibility that happens on WinForms/WPF/SL/ASP.NET:

- A synchronous method calls an async method, obtaining a `Task`.

- The synchronous method does a blocking wait on the `Task`.

- The `async` method uses `await` without `ConfigureAwait`.

- The `Task` cannot complete in this situation because it only completes when the `async` method is finished; the `async` method cannot complete because it is attempting to schedule its continuation to the `SynchronizationContext`, and WinForms/WPF/SL/ASP.NET will not allow the continuation to run because the synchronous method is already running in that context.

This is one reason why it's a good idea to use `ConfigureAwait(false)` within every `async` method as much as possible.

Solution C

`AsyncContext.RunTask` won't work in every scenario. For example, if the `async` method awaits something that requires a UI event to complete, then you'll deadlock even with the nested context. In that case, you could start the `async` method on the thread pool:

var task = Task.Run(async () => await MyAsyncMethod());
var result = task.WaitAndUnwrapException();

However, this solution requires a `MyAsyncMethod` that will work in the thread pool context. So it can't update UI elements or access the ASP.NET request context. And in that case, you may as well add `ConfigureAwait(false)` to its `await` statements, and use solution A.

Update: 2015 MSDN article 'Async Programming - Brownfield Async Development' by Stephen Cleary.

Problem

I have a `public async Task Foo()` method that I want to call from a synchronous method. So far all I have seen from MSDN documentation is calling `async` methods via `async` methods, but my whole program is not built with `async` methods. Is this even possible? Here's one example of calling these methods from an asynchronous method: Walkthrough: Accessing the Web by Using Async and Await (C# and Visual Basic) Now I'm looking into calling these `async` methods from synchronous methods.

Original source

Related problems