Earlier quoted context omitted.
"My point is, move these IO actions to another thread; the code in that thread is good old synchronous/threaded code." Sure. But how do you handle that? IO results need to be communicated back to the UI thread somehow. Throwing together a whole new thread+stack against a named method that communicates back via explicit messages (or however you want to get the results of IO back to the UI thread) seems like a bit much…
There is no problem to modify UI state from any thread; just put up some synchronizations. The hard part is, if the modifications do not form a single, predictable, serialized chain, how can the programmer reason about them? This problem is independent of async/sync. If you use C# async for a UI action, you still need to worry about it.
It reminded me of the "I know, I'll use regular expressions" joke.