>>>> If you never yield, then sure, but... that's not very useful in an asynchronous context. You might as well just go back to writing blocking C event loops where every task always runs to completion before any other task can start.
What you're talking about isn't what most people talk about or experience in regards to C# async, and it's still not an actual benefit. In all cases described so far, you're better off explicitly writing A to call B than to try to misuse an async task executor as a weird queue, especially as you said yourself that there is no yielding involved. It's really that simple. What you have described is incredibly brittle code riddled with implicit dependencies, and since you're not yielding, you are locking up the UI.
...But anyway, forget it. I'll be more than happy to use a multi-threaded UI system when such a thing exists.
>Whether the task gets interrupted or not is irrelevant — it will resume where it left off. As long as you synchronize access to global state [...]
Cooperative multithreading like async/await is leveraging the fact that actually if you control the interruption, THAT can be your synchronization. You don't need locks. UI programming is usually lock free. A UI thread is more commonly used. Understanding that, you can see that pre-emption _is_ sometimes a bug.