Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preventing a deadlock when calling an async method without using await

I need to call a method returning a Task from within

public override void OnActionExecuting(ActionExecutingContext filterContext)

It wont let me make this method async it throws the following

An asynchronous module or handler completed while an asynchronous operation was still pending.

and when calling

 entityStorage.GetCurrentUser().Result

I get a deadlock. How can I avoid this?

I have been playing around with it coming up with stuff like

entityStorage.GetCurrentUser().Result.ConfigureAwait(false).GetAwaiter().GetResult();

But this isn't working. How can I do it? My solution will need to work with ASP.NET 4 and the Async Targetting Pack, I can't use ASP.NET 4.5 as am deploying to Azure.

like image 594
Tom Avatar asked Aug 09 '12 16:08

Tom


People also ask

Can you call an async method without await?

The current method calls an async method that returns a Task or a Task<TResult> and doesn't apply the Await operator to the result. The call to the async method starts an asynchronous task. However, because no Await operator is applied, the program continues without waiting for the task to complete.

What happens if we execute an asynchronous method but do not await it?

If you forget to use await while calling an async function, the function starts executing. This means that await is not required for executing the function. The async function will return a promise, which you can use later.

Is it OK to not await async?

Using async void methods Every now and then you'll find yourself in a synchronous method (i.e. one that doesn't return a Task or Task<T> ) but you want to call an async method. However, without marking the method as async you can't use the await keyword. There are two ways developers work round this and both are risky.


2 Answers

The cause of the deadlock is explained here. In short, don't block on async code. You should use ConfigureAwait(false) in your library async code and await the results (not use Result or Wait).

Update: Please vote here for the MVC team to add support for async action filters.

like image 100
Stephen Cleary Avatar answered Sep 21 '22 17:09

Stephen Cleary


Since await is just syntax sugar for the compiler rewriting a continuation for you, the most 'direct' path would be to take whatever code was going to follow your await and make it a ContinueWith call.

So, something like:

entityStorage.GetCurrentUser().ContinueWith(t =>
{
    // do your other stuff here
});
like image 26
James Manning Avatar answered Sep 20 '22 17:09

James Manning