I see some colleague code where he chooses to not await the database call and just return the Task. E.g.
public Task<UpdateResult> AddActivityAsync(ClaimsPrincipal principal, Activity activity)
{
return _userManager.SaveToDatabaseAsync(principal, activity);
}
as _userManager.SaveToDatabaseAsync
is async, I would have implemented this way
public async Task<UpdateResult> AddActivityAsync(ClaimsPrincipal principal,
Activity activity)
{
return await _userManager.SaveToDatabaseAsync(principal, activity);
}
The calling method of this method always await it:
await _profile.AddActivityAsync(..., ...)
Is there any benefit to not make the inner method async and just return the Task, letting the caller await it ? I thought we had to write Async all the way down...
It depends on the situation.
You must await, for example, if the code to be awaited is bound to an object that is in an using
context (or gets manually disposed):
using (SomeDisposableType obj = ...)
{
await obj.SomeOperationAsync();
}
If you returned the task without awaiting it, then the method might complain that the object had been disposed before it could have finished its job. (not all disposable objects throw an ObjectDisposedException
if you attempt to perform something on them after they get disposed but it is generally a good idea to assume so). Consider the opposite:
using (SomeDisposableType obj = ...)
{
// This returns the Task that represents the async operation,
// and because it returns, the control goes out of the using
// scope, and therefore obj gets disposed.
return obj.SomeOperationAsync();
}
So there are cases when awaiting is necessary. If that is not the case, I can't really think of a reason why you couldn't return the Task
itself.
You do not need to await a method which returns a Task<T>
, the code will just run asynchronously if you have the async
keyword on the method. You colleague has removed that and so is running synchronously deliberately and lets the calling code implement it if they so choose.
It depends at which layer this code is being run. If it is deep it may be better to let the higher code layers choose ansynchronous execution and maintain control there.
You definitely don't need to 'write async all the way down'. The purpose of the async
keyword is simply to mark a method as being able to return a Task<T>
and be able to use the await
keyword. The await
keyword is what invokes the framework to execute the Task and provide asynchronous processing.
TL;DR: It's a choice.
I welcome anyone improving or correcting me on this as I am no guru.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With