Always use the keywords "async" and "wait" in asynchronous methods in the library?

Summary In the library method, when should I use the async and await keywords instead of directly returning Task ?

I believe that my question is related to this . However, this question is about .NET 4.0 and TPL, while I am using .NET 4.6 with the keywords async and await . So, I think my question might get different answers because these keywords did not exist when the related question was asked.

Explanation: I am writing a simple shell for an external WCF service, and the shell makes several SendAsync calls. Now I think that every wrapper method should just return the Task<> directly, without waiting. I understand that async / await should be used at the application level and not in the library.

So, for example, here is an approach that I think should take for each wrapper method:

 private Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return _service.SendAsync(request); } 

But on the Internet, I found several posts that use this approach:

 private async Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return await _service.SendAsync(request).ConfigureAwait(false); } 

And here is another example that I found in technet :

 async Task PutTaskDelay() { await Task.Delay(5000); } private async void btnTaskDelay_Click(object sender, EventArgs e) { await PutTaskDelay(); MessageBox.Show("I am back"); } 

So, when should I use the second approach (the one that includes the async and await keywords)? Why not just return the whole Task without creating a PutTaskDelay async ? I think I should return Task directly whenever possible, and use async / await to get the final result only at the application level. I'm right? If not, what is the difference between the two approaches that I show here?

My concern When the async and await keywords are used, it seems that it just provides extra work for the compiler without any benefits.

+13
c # asynchronous async-await
Mar 14 '16 at 12:18
source share
2 answers

Should I use async in the library?

It all depends. If you intend to use an asynchronous programming paradigm, then the answer is yes, the async and await keywords are needed most of the time. Most likely you will need to use async/await . This is due to the fact that in most situations it would be difficult to use only Task and Task<T> , since you will most likely have to reason about the results of the async operations that you invoke.

In addition, based on your question, it seems that you might have some confusion regarding the keywords themselves and their relation to the types Task and Task<T> . Let me clarify this for you.

The async allows you to use the await method. Best practice is to have all async methods return either Task or Task<T> if you cannot (for example, a button click event handler, as you showed above).

Methods that return Task or Task<T> represent asynchronous operations. When you are in the library, it is recommended that you use .ConfigureAwait(false) for the reasons described below here . In addition, I always point people to this detailed article on this subject.

To differentiate two approaches in your question:

The method below returns a Task<SignResponse> . This is an asynchronous operation that represents a login job. The method can be called by the caller to receive SignResponse .

 private Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return _service.SignAsync(request); } 

Similarly, this version does the same ... except that the async/await keywords are not needed. The reason they are not needed is because the method itself does not need to use SignResponse , and therefore it can simply return Task<SignResponse> , as shown above. And, as you pointed out in your question, there really is a penalty if you use async/await keywords when they are not needed. In this case, an additional step of the finite state machine is added, since the result is obtained, as it was expected.

 private async Task<SignResponse> GetSignDataAsync(SigningRequestType request) { return await _service.SignAsync(request).ConfigureAwait(false); } 

Finally, if you needed to substantiate the answer, you can use the above keywords to do this as follows:

 private async Task<SignResponse> GetSignDataAsync(SigningRequestType request) { var result = await _service.SignAsync(request).ConfigureAwait(false); if (result.SomeProperty == SomethingWeCareToCheck) { _log.Log("Wow, this was un-expected..."); } return result; } 
+7
Mar 16 '16 at 13:00
source share

Do not take my word for it, because I never understood async / I expect it well, but what bothered me most about this idea was that all methods using async should be marked as async, as well that annoyed me the end.

I believe that in a library in which people can choose how to use methods, this is good, so you should use async, however, I always found that it is clearer to explicitly use Tasks directly.

-2
Mar 16 '16 at 12:36
source share



All Articles