David Vedvick

Notes

Language Features and Inescapable Implementation Details

My main gripe with async/await in .Net, which makes the use of Task objects to look more similar to procedural code, is the recommendation that when using await in a library package, Task.ConfigureAwait(false) should be used in order to ensure the task doesn't continue on the called context. This is to prevent deadlocks on single-threaded synchronization contexts such as UI synchronization contexts.

An alternative approach to ConfigureAwait(...) could instead be syntax that improves the usability of synchronization context switching. Something like this:

 // New keyword "on", that then expects a synchronization context afterwards
var result = await longRunningProcess() on UISynchronizationContext;

This would have the benefit of giving the application developer improved control in the behavior of their app, while reducing the burden on library developers to make their async/await code "safe" for consumption.

I think this is a more general problem for any programming language introducing a concept meant to paper over the "hard stuff": invariably, the "hard stuff" creeps up, unless the sugary feature is very well thought out and future looking. And in the end, it seems the solution to the inescapable implementation details of syntactic sugar is introducing more syntactic sugar. I think there's a lesson here: for a new language feature to have successful adoption, it needs to minimize harm and maximize helpfulness...

Note posted on Monday, June 20, 2022 10:25 AM CDT - link