Assuming you just want to propagate exceptions, you have to mess with TaskContinuationSource (I.e, promises) and be damn certain you have wired it into all the right places.
Async/await makes error handling much more uniform and "obviously correct" than stringing callbacks together.
For any use case other than this there are other tools, such as WaitAll/WaitAny as you say.
[1] http://stackoverflow.com/questions/4070237/how-could-the-new...
I make it a rule never to question Eric Lippert, and I won't do so here. That said, right, the current continuation bit requires IL foo, but as the ones writing the code, there is always a way besides needing the current continuation bit.
And if you're going between languages much at all, Tasks are a lot more like promises and other paradigms in other languages. Whereas the whole await business is just... weird.
Nesting callbacks (ContinueWith) gets messy very quickly, and then your program structure and semantics are hidden behind masses of arcane ceremony.
Performing async calls dependent on previous async calls is hard enough to do correctly using ContinueWith, but try using it in a loop.
while (await reader.ReadAsync(cts)) { ... }In other words, the conditions you must satisfy for using Task.Wait or Task.Result are very complicated. They depend on and create global constraints of the entire program, and so you should avoid using them whenever possible.
0: http://blog.stephencleary.com/2012/07/dont-block-on-async-co...