The second example is a normal synchronous call, that is, DoFoo()
is running, at some point transfers the execution stream to Foo()
internally is practically a goto
, when it finishes executing another goto
is executed by returning to the following point where the Foo()
(there are some details of how it does this control that is not the case, even because it is internal to the processor).
The first example is still two normal functions, but the form of call is quite different, it is asynchronous that allows the execution to be released to perform other things.
There is a complex infrastructure mounted by the C # compiler to control a state machine that controls the execution of the methods. Not just a simple flow deviation. And there's a graph that shows how the flow becomes complex:
Notetheblackflowasitgoesbackandforthinanormalway.Theredstartsexecutionofthefunctionbutmaynotendupallowinganotherflowtorunfromthere,evenwhilethatfunctioniswaitingforexternalresponsessuchasdisk,network,servicesanddatabase.
Sothedifferenceisthattheasynchronousmethodwaitsfortheendoftheexecutionofthefunctionbutallowsanotherflowtobeexecuted,whereasthesynchronousmethodstopstherewaitingfortheprocessingtoend.
Butithasnomiracle,somehowyouhavetohaveaninfrastructurethataccessestheexternalenginegivingthechanceofanotherflowtoexecute.Ifyouareonlyconsumingsomethingyoudonothavetoworrytoomuch,butifyouarewritingexternalaccessyouneedtocoordinatethis.Here'sanexampleof how is access to asynchronous file reading , is not so trivial.
There has always been an asynchronous form in .NET, but it was very complicated to consume because you had to write the code to coordinate the flow, now the compiler writes for you.
I'm not going to go into details about utility and functionality because there are already several answers to this: