To await or not to await - that is the question

One question that comes up quite often is if you should always use async/await or not. Sadly enough the answer is not simple because there is a trade-off between performance and ease of understanding exceptions.

So when you implement a method that returns a Task in .Net there are three different categories of methods you will implement. Methods that are synchronous, methods that need to use the result of an asynchronous operation and methods that don't need the result of an asynchronous operation.

The first two are easy. If you method returns a Task (probably because you are implementing some interface) but does so synchronously you should never use the async keyword on that method. If your method needs the result of another method returning a Task you should on the other hand always use the async keyword and await that task.

The tricky one is when your method don't need the result. These methods all end with a call to a method returning a Task and you don't need any special error handling and hence you can either just return the Task returned by the method called or you can await it. Which of the two you do depends on what your application is.

Using async/await is always a small overhead since the compiler will create a small state machine for you as well as create a new Task object for the returned result. All this is avoided if you can just return the Task returned by another method. The downside with this approach however is that if that inner method throws an exception the stack trace will not have the method where you did not await and hence the investigation of an unexpected stack trace can become harder since part of your stack trace is just missing.

I created a small snipped you can find here that I used in LINQPad to demonstrate the difference. So it will really be up to your preference. In a service you might want to optimize and not use async/await since that will reduce execution time as well as generated garbage for the GC to collect. In all other cases or where you want to make sure you never loose part of a stack trace you should await.

Naturally the fact that you need stack traces to understand what is wrong rather than logs and the actual information in your exception message is a different topic...

No comments:

Post a Comment