问题
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.
回答1:
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
});
回答2:
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.
回答3:
If you MUST convert asynch to synch.
public User GetCurrentUserSynch()
{
return Task.Run(() =>
{
var asyncResult = entityStorage.GetCurrentUser();
while (!asyncResult.IsCompleted)
{
Application.Current.TryFindResource(new object()); // This is for WPF but you can do some other nonsense action of your choosing
}
return asyncResult.Result;
}).Result;
}
Otherwise use @Stephen's answer.
来源:https://stackoverflow.com/questions/11887915/preventing-a-deadlock-when-calling-an-async-method-without-using-await