Sunday, May 3, 2015

Key takeaways from working with async/await in C#

There is a lot of information available around the web about asynchronous programming with async/await in C#. In this post I am going to explain my personal key takeaways.
In general, the pattern is all about avoiding to have threads in idle state, doing nothing but waiting for some time consuming operation to finish (you also have better things to do than waiting for the pizza in front of your door after you ordered it, right?).
Why is this needed? There are two scenarios: In user interfaces, the "free" UI thread can be used to react on user actions while the asynchronous operation takes place. User actions can be things like moving the window around, resizing, clicking buttons and so on. On the server side (e.g. in an ASP.NET web application), the "free" threads can be used to process other requests, i.e. the application's scalability will be improved.

For further discussion let's have a look at the following example code from MSDN:

1:  async Task<int> AccessTheWebAsync()  
2:  {   
3:    HttpClient client = new HttpClient();  
4:    Task<string> getStringTask = client.GetStringAsync("");  
5:    DoIndependentWork();  
6:    string urlContents = await getStringTask;  
7:    return urlContents.Length;  
8:  }  
  • Async and await are appearing together: async is part of the method signature, await is used at least once within the method (Lines 1 and 6)
  • An async method returns Task<T>, Task or void (in rare cases) (Line 1)
  • Tasks can be considered as "containers" of work that has to be done.
  • There is a convention that says async method names should be postfixed with "...Async" (Line 1)
  • When an async method is called, the work within this method is kicked off but usually not finished, hence the return value is not the final result (string in this case) but the task which encapsulates the work (Line 4).
  • You can do other stuff while the async task is being performed (Line 5)
  • When our code hit's await it either continues processing when the result is already available, or - when the result is not yet available - it will for now pass control back to the caller. But await implies a promise that once the result is available the program will jump back continuing processing the result (Line 6).
  • The naming of "await" is a bit misleading. Think of it as "continue after task has been finished", i.e. in the above example: "continue after getStringTask has been finished" (Line 6)
  • For an async method, internally a state machine is created by the compiler that does all the heavy lifting.
  • Note that the datatype represents is a string and not a task any more, i.e. await automatically unwraps the generic type parameter from the Task (Line 6).
  • async/await are often going up the complete call stack, i.e. all the methods in the stack are async
An interesting source of information you might want to check out when working with asynchrony in C# is the article "Best Practices in Asynchronous Programming" from MSDN magazin.