When control reaches the await
statement in Cube3
, Task.Delay()
is called and immediately returns a Task
that will complete after the delay. The rest of CalculateAnswer()
is refactored into a continuation that will run when the Task
returned by Delay()
completes, and CalculateAnswer()
immediately returns a Task<int>
that will complete when that continuation completes.
CallCalculateAnswer()
awaits the Task<int>
returned by CalculateAnswer()
, so the same logic applies: the code running after the await
(i.e. the return
statement) is refactored into a continuation that will run when the Task<int>
completes, and CallCalculateAnswer()
proceeds to return its own Task<int>
.
StartChain()
, however, does not await the Task<int>
produced by CallCalculateAnswer()
, so no continuation is generated. Instead, it stores the task into a local variable and returns. Therefore, the orange arrow in your question is the right one.
Note that, in this specific case, since nothing is done with the Task<int>
returned by CallCalculateAnswer()
and it is only stored in a local variable, it becomes "forgotten" once StartChain()
returns: the task will complete (or fail) some time in the future, but its result (the int
it produces) will be lost.
Update following comments: The pink arrow in your question implies you're expecting StartChain()
to block, waiting for the task returned by CallCalculateAnswer()
to complete, because it is not async
and does not await
that task. This is not what happens, as the usual control flow semantics apply: the method has returned a task, so you get a reference to that task and nothing more.
If you want StartChain()
to block, you can use Task.Wait(), Task<T>.Result
, or similar on the task returned by CallCalculateAnswer()
.