how to make async calls to run synchronously in c#

1.4k views Asked by At

I have this this code

ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password)

I want this code piece to run Synchronously, because my very next statement is depend upon this. Below call fails most of the time because user is null.

var roles = await userManager.GetRolesAsync(user.Id);

Any suggestion?

3

There are 3 answers

0
Panagiotis Kanavos On

There is nothing wrong with the code. await means that execution continues only after the asynchronous method that follows finishes. This means that in this snippet:

var user = await userManager.FindAsync(context.UserName, context.Password)
var roles = await userManager.GetRolesAsync(user.Id);

the call to GetRolesAsync will be executed only after the previous line completes.

From the documentation of UserManager.FindAsync

Returns a user with the specified username and password or null if there is no match.

Either the username or password are wrong. Just return a message to the end user asking them to retry. If you make this call using stored credentials, check them again.

In any case, you need to check for an authentication failure before trying to use the user value, eg:

var user = await userManager.FindAsync(context.UserName, context.Password)
if (user == null)
{
    //Somehow report failure, decrement retry counters, etc
    retries--;
    return false;
}
else 
{
    var roles = await userManager.GetRolesAsync(user.Id);
    ....
}
6
Stefan Steiger On
ApplicationUser user = userManager.FindAsync(context.UserName, context.Password).Result;
var roles = userManager.GetRolesAsync(user.Id).Result;

But if the context user just is null, it won't help you if you do it synchronously - user will be just as NULL as it was before.

If you are trying to add a login to your application, it might help to check out this.
Also, you should probably use policies instead of roles.

Edit:
OK, without deadlock-problem I was unaware of (thanks @hvd):

var user = Task.Run(() => userManager.FindAsync(context.UserName, context.Password)).Result;
var roles = Task.Run(() => userManager.GetRolesAsync(user.Id)).Result;

If the async method returns void

Task.Run( () => asyncMethod()).Wait();
1
pwas On

I don't see why there could be problem - if you await properly, user should be properly fetched before GetRolesAsync call. Is this your whole code?

Mayby, user is null because it doesn't exist?

Besides, you can chain your calls instead of running it synchronously:

var roles = await userManager.FindAsync(context.UserName, context.Password)
                             .ContinueWith(task => 
                                              userManager.GetRolesAsync(task.Result.Id))
                             .Unwrap();