Summary: In a library method, when should I use the async
and await
keywords instead of returning a Task
directly?
Should I use async await in library?
It all depends. If you're going to take advantage of the asynchronous programming paradigm, then the answer is "yes," the async
and await
keywords are needed most of the time. More than likely, you will find yourself needing to use async/await
. That is because in most situations it would be difficult to use only Task
and Task
as you will more than likely need to reason about the results of the async operations that you invoke.
Additionally, based on your question it seems as though you may have some confusion about the keywords themselves and how they relate to the Task
and Task
types. Allow me to clarify this for you.
The async keyword allows a method to use the await keyword. The best practice is to have all async methods return either Task
or Task
unless you are unable to (for example, a button click event handler as you demonstrated above).
Methods that return Task
or Task
represent asynchronous operations. When you are in a library it is suggested to always use .ConfigureAwait(false)
for reasons detailed here. Additionally, I always point people to this detailed article on the subject.
To differentiate the two approaches in your question:
The method below returns a Task
. This is an async operation that represents the work to sign in. The method can be awaited by the caller to get SignResponse
.
private Task GetSignDataAsync(SigningRequestType request)
{
return _service.SignAsync(request);
}
Likewise, this version does the same thing...except that the async/await
keywords are not needed. The reason they are not needed is that the method itself does not need to use SignResponse
and therefore it could simply return Task
as shown above. And as you indicated in your question, there is indeed a penalty when you use the async/await
keywords when they are not needed. Doing so adds an extra state machine step as the result is yielded, since its awaited.
private async Task GetSignDataAsync(SigningRequestType request)
{
return await _service.SignAsync(request).ConfigureAwait(false);
}
Finally, if you needed to reason about the response, you could use the aforementioned keywords to do so like this:
private async Task GetSignDataAsync(SigningRequestType request)
{
var result = await _service.SignAsync(request).ConfigureAwait(false);
if (result.SomeProperty == SomethingWeCareToCheck)
{
_log.Log("Wow, this was un-expected...");
}
return result;
}