This question has already been answered:

I read a lot of literature, but I still can’t understand how await and async . Well, at least kill. Everywhere examples with httpclient, but for me they are not clear. I'm trying to figure it out myself. Here is what I understood:

As soon as our code encounters await, control returns. After completion of the expected operation, the method is restored. More precisely continues to perform from the place where he stopped when faced with await.

Ok, I wrote a couple of lines of code (maybe I just did something wrong)

 async Task myMethod() { int sum = 0; await SomeCycleAsync(); Console.WriteLine("выполнился Ρ†ΠΈΠΊΠ»2"); } async Task SomeCycleAsync() { var myTask = await ResultOfCycle(); Console.WriteLine("выполнился Ρ†ΠΈΠΊΠ»1"); } async Task < int > ResultOfCycle() { int sum = 0; for (int i = 0; i < 1000000000; i++) { sum += i; } return sum; } private void Form1_Load(object sender, EventArgs e) { myMethod(); } 
  1. In the myMethod method, the word await occurs and, as far as I understand, the control should go back to form_load , right?

  2. During the execution of the SomeCycleAsync method, await is encountered, i.e. logically, management should go to Console.WriteLine("выполнился Ρ†ΠΈΠΊΠ»2"); But the result of this work is:

run cycle1

run cycle2

Please explain to me why? I don't understand at all

Marked as a duplicate by the participants andreycha , Grundy , aleksandr barakin , user194374, dirkgntly Aug 25 '16 at 9:54 .

A similar question was asked earlier and an answer has already been received. If the answers provided are not exhaustive, please ask a new question .

  • So you have everything in one thread, so the result is as follows. Try experimenting with threads. - Morgot
  • > In the myMethod method, the word await is found, and as far as I understand it, the control should go back to form_load, right? await is an operator that says "wait until the result is received". The control does not go somewhere - at that moment the thread stops and waits until SomeCycleAsync returns the result. The whole point is to send the task for processing, go about your business, and call await only when you need the result of an asynchronous function. So you can quite flexibly work with braking operations without blocking and full multithreading. - etki

2 answers 2

See it.

async / await alone does not mysteriously include multithreading / asynchrony. They only create conditions under which this asynchrony is easy to implement.

In fact, when the async method is called, the following happens.

  1. Starts to run synchronously async method. If this method ends before the first await , the result is delivered synchronously, and the already completed , completed Task returned from the method.
  2. If await encountered during execution, the system checks to see if the task that await was called on has completed. If this task has completed, then its result is substituted, and synchronous execution continues further.
  3. If the task on which await occurs has not yet been completed, at that moment an incomplete Task returned from the method. At this point, the outer code takes control and continues to execute. For example, this code can write a Task to a variable and continue to go about its business. Or it can execute await on the received Task , and since this Task is not completed yet, the external code at this moment will similarly give control to even more external code, and. etc.
  4. When the Task to which await occurs ends (producing a result or an exception), the code after await resumes its work.

In your case the following happens:

  1. Called Form1_Load .
  2. The line myMethod(); . This code will produce a Task , which will later be simply ignored.
  3. The code for the myMethod method myMethod . It is executed synchronously int sum = 0; . To execute the next line, first you need to run the SomeCycleAsync method and then await on the resulting Task .
  4. SomeCycleAsync execution SomeCycleAsync . To get the Task 's, for which you need to do await , the ResultOfCycle method is ResultOfCycle .
  5. ResultOfCycle() starts. Since there are no asynchronous calls anywhere in it, it runs completely synchronously. The completed Task returned from the method.
  6. Control returns to SomeCycleAsync . Running await on Task , obtained in the previous paragraph. Since this Task already completed, an int result is simply written to the myTask variable. The line Console.WriteLine("выполнился Ρ†ΠΈΠΊΠ»1"); . This completes the SomeCycleAsync method. Since there was no asynchronous wait, the completed Task returned.
  7. Control returns to the myMethod() method. Starts await on the received Task . Since the Task completed, nothing happens, the method continues to run synchronously. The line Console.WriteLine("выполнился Ρ†ΠΈΠΊΠ»2"); , the method ends by returning the completed Task .
  8. Control returns to Form_Load . The received Task ignored, the execution ends.

For your goals, it would be better to explicitly run the calculations in an asynchronous manner. For example:

 async Task myMethod() { await SomeCycleAsync(); Console.WriteLine("выполнился Ρ†ΠΈΠΊΠ»-2"); } async Task SomeCycleAsync() { Console.WriteLine("стартуСт Ρ†ΠΈΠΊΠ»"); // это запускаСт Π΄Π»ΠΈΠ½Π½ΠΎΠ΅ вычислСниС Π½Π° ΠΏΡƒΠ»Π΅ ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² var result = await Task.Run(ResultOfCycle); Console.WriteLine("выполнился Ρ†ΠΈΠΊΠ», Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚: " + result); } int ResultOfCycle() { int sum = 0; for (int i = 0; i < 1000000000; i++) sum += i; return sum; } private async void Form1_Load(object sender, EventArgs e) { await myMethod(); } 
  • So await myMethod(); will still create a lock on the current thread. Is not it so? - iRumba
  • @iRumba: No, does not create - if the method myMethod written correctly (and does not block the stream itself). Since async / await is cooperative multitasking, async methods must be implemented without errors in order for everything to work as it should. - VladD
  • one
    @iRumba: The lock will only be until the first await inside myMethod. The author of the method must make sure that it is not for long. - VladD
  • and if you write instead await myMethod(); var t = await myMethod(); ? - iRumba
  • In general, await means waiting for the task to complete, which means that Form1_Load hangs on waiting, isn't it? - iRumba

Your ResultOfCycle() should return Task<int> , but return a sum , which is just an int . In the method itself there is no second thread in which it would be executed. Await is written before a Task object or by a method that returns a Task object.

Example for Task (calling a function that returns nothing):

 static void Main(string[] args) { My(); for (int i = 1; i <= 10; i++) { Thread.Sleep(1000); Console.WriteLine($"* {i*1000}"); } Console.ReadLine(); } static async void My() { await GetMessage(3000); } static Task GetMessage(int time) { return Task.Run(() => { Thread.Sleep(time); Console.WriteLine($"zxzxz {time.ToString()}"); }); } 

Example for Task<T> (calling a function that returns an object of type T or in our case string ):

 static void Main(string[] args) { My(); for (int i = 1; i < 10; i++) { Thread.Sleep(1000); Console.WriteLine($"* {i*1000}"); } Console.ReadLine(); } static async void My() { string message = await GetMessage(3000); Console.WriteLine(message); } static Task<string> GetMessage(int time) { return Task.Run(() => { Thread.Sleep(time); return $"zxzxz {time.ToString()}"; }); }