It does look odd, though the explanation below the code may shed some light:
"Because a console application may terminate before the continuation task executes, the WaitAll method is called to ensure that both the original task and its continuation finish executing before the example ends."
In other words, waiting on both
dTask and
dTask2 is there to guard against a situation in which dTask completes and dTask2 has not started execution yet, as the console app will not be able to wait on dTask2 returned by
Task.Factory.StartNew()
It might be worth bearing in mind that dTask2 does not execute in itself but rather kicks-off an asynchronous task. In this respect, dTask2 can be viewed as a wrapper which spawns an inner task, and calls Task.Run() on this inner task. Waiting on dTask2 would not work, as it immediately returns after spawning off the inner task. It should be possible to unwrap dTask2 and wait on its inner task, though this is probably not what is intended here - being as tasks were created using
Task.Factory rather than more directly using the constructor. Here is an interesting blog which is centred around this topic:
Task.Run vs Task.Factory.StartNew, by Stephen Toub[
^]
Some of this complexity, perhaps, stems from dTask2 being asynchronous. It would be interesting to explore whether this could be avoided by running
dTask and dTask2 in
sequence continuation (as opposed to
parallel continuation) using the fluent interface pattern, chaining
.ContinueWith(dTask2 => ... onto
Task.Factory.StartNew()