Language Features and Inescapable Implementation Details
My main gripe with
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