Technically, this works, but it works by creating a new thread to perform a synchronous operation, which itself is wrapping and locking on its asynchronous operation. This means that you are not getting some of the biggest benefits of switching async in the first place.
The correct way is completely asynchronous. If right now you have something like this:
private class UserService { public IdentityUser GetById(int id) { return mContext.Users.Single(u => u.Id == id); } }
... now you should create an asynchronous version:
private class UserService { public async Task<IdentityUser> GetByIdAsync(int id) { return await mContext.Users.SingleAsync(u => u.Id == id); } }
Using:
public async Task<IdentityUser> GetByIdAsync(int id) { return await _userService.GetByIdAsync(id); }
Assuming your underlying infrastructure supports asynchronous methods, such as SingleAsync() for inherently asynchronous operations, this will allow the system to free the current thread while you wait for the database operation to complete. This thread can be reused elsewhere, and when the operation is completed, you can use any thread available at that time.
It may be worth reading and accepting these best practices . You probably want to use .ConfigureAwait(false) anywhere you don’t get access to contextual information, such as sessions and queries.
This answer assumes, of course, that GetById is inherently asynchronous: you are retrieving it from a hard drive or network location or something like that. If it calculates the user ID using long-running CPU, then Task.Run() is a good way, and you probably want to further indicate that this is a long-term task in the arguments of Task.Run() .
source share