2

( I've read a lot about async and I wonder what happens if there is a mix of async function call and non-async) and im talking about THREAD pov .

( I know that mix should not be done , but im asking in order to understand the flow better)

suppose I have(cube 1) function which calls async functions which calls asyc function.

(please notice that cube 1 function is not async)

Question : when the control reaches (cube 3) await Task.Delay(100); --

what is really happening as the control reaches cube3 await ? does the control is back(and blocked) at the pink arrow (cube 1 ) or does the control is released and still awaits ( orange arrow)

enter image description here

Royi Namir
  • 144,742
  • 138
  • 468
  • 792

1 Answers1

2

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().

Frédéric Hamidi
  • 258,201
  • 41
  • 486
  • 479
  • _When control reaches the await statement in Cube3, Task.Delay() is called and immediately returns_ -----returns to where ? – Royi Namir Jul 14 '13 at 08:22
  • @Royi, to its caller, `CalculateAnswer()`, as usual. – Frédéric Hamidi Jul 14 '13 at 08:23
  • Nope, to its immediate caller, like any function call. What makes you think control would skip an execution frame in that case? – Frédéric Hamidi Jul 14 '13 at 08:25
  • I was thinking that the orange one will be the right one only if startChain was async... – Royi Namir Jul 14 '13 at 08:27
  • @Royi, it looks like you're thinking that calling an `async` method without awaiting the task it returns will block, waiting for that task to complete. That is not what happens, the control flow remains exactly the same as usual: the method has returned a task, so you get a reference to that task, nothing more, nothing less. If you want `StartChain()` to block, you can use [Task.Wait()](http://msdn.microsoft.com/en-us/library/dd235606.aspx) or similar on the task returned by `CallCalculateAnswer()`. – Frédéric Hamidi Jul 14 '13 at 08:30
  • you read my mind. that's what i was thinking actually. ( that if startChain is not async , so the control **waits at the pink arrow** ,after bubble up) – Royi Namir Jul 14 '13 at 08:33
  • 1
    Concerning the last paragraph of this answer: [Don't Block on Async Code](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html) – cremor Jul 15 '13 at 05:49
  • @FrédéricHamidi Does the system yields 2 tasks to await? ( both for cube 2 and 3 ? ) – Royi Namir Jul 16 '13 at 10:33
  • @Royi, I'm not sure to understand, can you clarify what you mean by "two tasks to await"? – Frédéric Hamidi Jul 16 '13 at 10:37
  • @FrédéricHamidi When the control reaches cubes 2 await , does it OPen a task to listen to , and also for the await of cube 3 ? – Royi Namir Jul 16 '13 at 10:38
  • @Royi, a new `Task` is returned from `CallCalculateAnswer()`, as the function awaits the `Task` returned by `CalculateAnswer()`, yes. – Frédéric Hamidi Jul 16 '13 at 10:42
  • Well I dont think so cuz [from here](http://blog.stephencleary.com/2012/02/async-and-await.html) -- _Await examines that awaitable to see if it has already completed; if the awaitable has already completed, then the method just continues running (synchronously, just like a regular method)_ and also [becuase of my question yesterday](http://stackoverflow.com/questions/17661428/async-stay-on-the-current-thread) - please look at B and D they are both on the same thread....(different thread from main but SAME thread BOTH)(im asking you just to be sure) – Royi Namir Jul 16 '13 at 10:44
  • @Royi, well, if the awaited task has already completed, then `await` if indeed effectively ignored and the execution continues as if the keyword was not specified. In the general case, though, awaiting does mean the function returns. – Frédéric Hamidi Jul 16 '13 at 12:28