Tuesday, April 16, 2019

I saw Keith Voels speak on async/await in C# at the Twin Cities Code Camp three days ago.

The third of five talks I saw here gave me Keith. I always assumed that you were breaking onto a new thread whenever you called a method that had the async keyword decorating it and you are, but it is important to understand that you are not necessarily staying on the same thread in the entire time during the independent act. What is more, you are not necessarily rejoining the main "God" thread either. The async/await paradigm's TAP (task-based asynchronous programming) manages boxing stuff up and putting it on a shelf so that another thread can pick it up seamlessly to you. Why change threads at all? Keith Voels showed off the performance from an app built with manually changing threads the old (hard) way versus the same app built with async/await and there were naturally places where, in the first app, one thread ended up doing a little more than the others running at the same time creating a noticeable bottleneck thus translating to a performance gap in contrast to the second application. Another thing I learned is that you really should await all async methods as if you don't the async process is vulnerable to being cleaned up by garbage collection. I am guilty of often creating void async methods and not awaiting their return. This I should not have done. ExecutionContext is the term for the async paradigm's modestly complicated, nuanced management of threads. The SynchronizationContext I believe captures the EC (ExecutionContext) at any given fork in the road and can be used to rejoin child threads to a consistent main thread. The need for a consistent UI thread arises in WinForms and WPF applications which freak out if the initial thread is lost. ConfigureAwait is the magic to determine whether or not we rejoin the main UI thread. .ConfigureAwait(false) must be explicitly used on all awaits to not circle back to the main UI thread. I guess this may hang off of everything that returns Task. It was deemed that it would just be too much overhead to ask WinForms and WPF developers to sprinkle .ConfigureAwait(true) everywhere. Use Task.Delay instead of Thread.Sleep in the new approach. You do not want to mix the old ways and the new in any shape as the ExecutionContext is not smart enough to compensate for you not being smart yourself. System.Threading.Task and System.Thread are not playmates. It is possible to send an async thread(s) a CancellationToken as a conditional flag to make it stop doing what it's doing and just wrap up and return right away.

No comments:

Post a Comment