Reputation: 3121
I'm doing some OAuth work, where I get my refresh token through an provided async API method (GetRefreshTokenAsync):
public async Task<Tokens> RenewAuthentication()
{
AppTokenResult token = await OAuth.GetRefreshTokenAsync("clientid",
"clientsecret",
@"myRefreshToken");
string accessToken = token.AccessToken;
string refreshToken = token.RefreshToken;
return new Tokens(accessToken, refreshToken);
}
If I call this like from a non-async method as such:
public void noAsync()
{
var r = RenewAuthentication();
var x = r.Result;
}
It deadlocks the app :(. If I remove the 2nd line (r.Result), then it works, but that's crap, because I can't get the result. I tried reading
http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
But after trying his method 1 by adding .ConfigureAwait(false) to the GetRefreshTokenAsync() method it didn't make any difference.
Any advice?
Upvotes: 2
Views: 1083
Reputation: 63722
You need to make sure the result of RenewAuthentication
isn't marshalled back to the UI thread. ConfigureAwait(false)
is pretty much exactly for a purpose like this:
var renewAwaitable = RenewAuthentication().ConfigureAwait(false);
var result = renewAwaitable.GetAwaiter().GetResult();
However, I'd suggest with going all-out with async instead. There isn't really a reason to block anywhere in a UI application - just disable whatever controls must not be used while waiting for the token to come back, and enable them when it does.
Upvotes: 1
Reputation: 149518
It deadlocks the app :(
That's what blocking on an async
method in an environment that has a custom synchronization will do.
If you call this on "FormLoad", you don't need to block. Simply mark you event handler as async
so you can await
on the operation:
public Form()
{
this.Load += OnLoadHandler;
}
public async void OnLoadHandler(object sender, EventArgs e)
{
var result = await RenewAuthenticationAsync();
// Store the result here
}
Upvotes: 5
Reputation: 14334
async
code is an all the way construct. You cannot do half async and should not try to force it. noAsync
appears to do nothing useful here.
In his wisdom, Mr Cleary makes it clear that each async
method has its own context in which it may run continuation on the UI.
Can you be sure that OAuth.GetRefreshTokenAsync
is using ConfigureAwait(false)
internally? If it doesn't, you will deadlock.
Upvotes: -1
Reputation: 41
If you access the Result property of a Task, it will act as a Future and it will block the current thread until the Task returns with the result.
I don't think you actually got a deadlock, but the Task you're waiting for never finishes.
Make sure your call to OAuth.GetRefreshTokenAsync returns.
Upvotes: 1