-1

I never had a good chance to go deep into async/await , so I have just a gist of what it does.

So I tried it in WinForms app like this:

private async void button2_Click(object sender, EventArgs e)
{
  // In below line I understand the Task is created and scheduled to execute, which in this
  // simple case means, that it executes right away asynchronously.
  var task = Task.Factory.StartNew(() =>
  {
    Task.Delay(5000).Wait();
    return 12;
  });

  // Here we wait for the task to finish, so we don't see MessageBox yet.
  var res = await task;
  MessageBox.Show("Result is :" + res);
}

My question is, since we are waiting on await I expected to block UI thread, since we can go any further in that thread (to the line with MessageBox). So UI thread actually stops on method with event hadnler.

But, to my surprise, windows is responsive and everything works very well, but I didn't expect that. Can anybody explain me what is going on?

After reading this post, I still have a doubt, if await is asynchronous and doesn't block UI thread in my example, why the thread doesn't proceed to next line with MessageBox? How the UI thread proceeds then?

Is good idea that code after await is just another Task, like in ContinueWith? But it comes back to UI context?

Michał Turczyn
  • 32,028
  • 14
  • 47
  • 69
  • `async void` means the UI thread doesn't wait for it. – ProgrammingLlama Mar 19 '20 at 06:13
  • 3
    _"windows is responsive and everything works very well, but I didn't expect that"_ -- and yet, that is _exactly_ the whole point of `await`. The method returns at that point, and will resume execution later when the awaited object completes. In the meantime, that thread is freed up to do whatever else it wants to do. This is _fundamental_ to how async/await works, and we have lots of questions (hundreds, if not thousands) on the site that already explain all of this quite well. See marked duplicate for one of the most-referenced/most-thorough ones. – Peter Duniho Mar 19 '20 at 06:15
  • I am by no means an async expert, but from what I understand, once the code in your async method reaches the `await` keyword, the flow returns to the calling method until the task awaited is completed, and only then the flow resumes to the rest of the async method. – Zohar Peled Mar 19 '20 at 06:16
  • `await` is not `Wait`. When the code hits the `await` keyword, the method returns immediately, after registering a continuation to the completion of the awaitable. The continuation contains anything that is below the `await` line. In your case it contains the `MessageBox.Show` command. When the awaitable completes, then the registered continuation will run. – Theodor Zoulias Mar 19 '20 at 06:16
  • 1
    Probably this operator would be less confusing if instead of the neat `await` had a more descriptive name, like `continueAfterCompletionOf`. Of course such a long keyword would have other disadvantages. – Theodor Zoulias Mar 19 '20 at 07:15
  • async/await is never about threads. It's all about tasking, like leveraging idle threads as much as possible. Think of async / Promise in Javascript, there's one thread, you still can do async. Async is all about context. When it blocks, it blocks the context, and return / free the thread, so that the thread can do something else. Code after the `await` is continuation of the completed task, like the ones created using `ContinueWith` but simpler. By default, it ALWAYS come back to the same context, but not necessarily on the same thread. – weichch Mar 19 '20 at 08:09
  • @TheodorZoulias IMO opinion, `async` has that disadvantage, that it can lead sb (like me) into false thinking, like I presented in questio, that rest of a code will be executed as it would be normally, on the same thread. Instead, it gets "packed in other task", and scheduled to execute after `await` returns. – Michał Turczyn Mar 19 '20 at 08:57
  • I agree Michał. async/await had me confused for months, until I finally got it. It's a wonderful tool, but it has a long demystification period! – Theodor Zoulias Mar 19 '20 at 10:01
  • I recommend these as introductory resources: [async intro](https://blog.stephencleary.com/2012/02/async-and-await.html), [async best practices](https://learn.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming), [official docs](https://learn.microsoft.com/en-us/dotnet/csharp/async). On a side note, [use `Task.Run` instead of `Task.Factory.StartNew`](https://blog.stephencleary.com/2013/08/startnew-is-dangerous.html). – Stephen Cleary Mar 19 '20 at 13:26
  • @StephenCleary Thanks a lot :) I have read your articles on this several times in the past, but I couldn't get my head around this. But now I start understanding this :) Also, I prefer `StartNew`, as this gives great control over how tasks are handled. – Michał Turczyn Mar 19 '20 at 13:58

1 Answers1

1

Async methods are a lot like generator methods. The compiler will split up your code at each await operator. A block of code is inserted to check if the task is already complete, in which case the method immediately continues. Or if the task is not complete, a callback is registered to continue execution later, and your method returns.

Returning early is the whole point of an async method.

Jeremy Lakeman
  • 9,515
  • 25
  • 29