How is Task.WaitAll different from Thread.Joining a bunch of threads? Or if you were cancelling tasks, using cancellation tokens?
The other comment alluded to this, but the crux of the problem is that you can schedule a task to run and wait on the completion of that task, but the only available thread for it to run is the one currently waiting for it to complete. The writeup here isn't bad: https://devblogs.microsoft.com/pfxteam/await-and-ui-and-dead...
If you are running Task.WaitAll on a UI thread you are likely to create a deadlock.
I just finished an app that had to shutdown while some async operations were still not finished. Really hard to manage compared to using threads.