I read somewhere on Stackoverflow in a comment the following analogy. Because in the comment I can not find it easily, so there is no link to it.
Suppose you have to have breakfast. You cook some eggs and smoke bread.
If you start to boil eggs, then somewhere in the Boil Egg subroutine you will have to wait until the eggs are boiled.
It would be synchronous that you wait until the eggs have finished boiling before starting the Toast Bread routine.
However, it would be more effective if, while the eggs are boiling, you do not wait, but begin to fry the eggs. Then you wait until one of them finishes, and continue the “Boiled Eggs” or “Toast Bread” process, which ends first. It is asynchronous, but not parallel. This is still one person who does everything.
The third way is to hire a cook who boils eggs while you are baking bread. This is really simultaneous: two people are doing something. If you are really rich, you can also hire a toaster while you read the newspaper, but hey, we don't all live in Downton Abbey ,-)
Back to your question.
Nr 2: synchronously: the main thread does all the work. This flow returns after the egg boils before the caller can do anything else.
Nr 1 is not declared async. This means that although you are launching another thread that will do this work, your caller cannot continue to do anything else, and although you can do this, you simply cannot wait for the egg to boil.
The third procedure is declared async. This means that as soon as the waiting for the egg begins, your caller can do something else, such as toasting bread. Please note that this work is completely performed by a single thread.
If your caller waits to do nothing but wait for you, it will not be very useful if your caller is also not declared async. This would give the caller the opportunity to do something else.
As a rule, when using async-wait correctly, you will see the following: - Each function declared async returns Task instead of void, and Task <TResult> instead of TResult - There is only one exception: the event handler returns void instead of Task. - Each function that calls the async function must be declared as aync, otherwise using the async wait is not very useful. - After calling the asynchronous method, you can start toasting the bread while the egg is boiling. When the bread is toasted, you can wait for the egg, or you can check if the egg is ready during the toast, or maybe it would be most effective to wait for Task.WhenAny to continue the finishing egg or toast or wait for Task. WhenAll when you have nothing useful, if not both completed.
Hope this analogy helps