So yes "async" is easy, but "multithreaded/parallel" is a lot more error prone and explicit.
EDIT: I should also note I havent been in the space for a few years so Im not fully current on how it looks today
Multi-threaded/parallel is a LOT easier now with the Task Parallel Library (TPL, https://learn.microsoft.com/en-us/dotnet/standard/parallel-p...) and System.Threading.Channels. Channels in particular are nice because it can fan out and then back in to one aggregator, removing the need for self managing synchronization primitives.
I usually default to channels first, TPL when I want threads.
Greenthreads or what have you are not a replacement if you want to do things like have a UI thread or bind to a native thread for interop. But you _can_ with async/await.
ConcurrentML really brought dotnet's concurrency story into the 1990s.