Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an "async void" method run synchronously?

Here Eric Lippert says:

A void returning async method cannot be awaited; it is a "fire and forget" method. It does work asynchronously...

It does work asynchronously right?

To test that, I made a windows form application and handled one arbitrary event. Inside handler, I started a heavy computation. Clearly, it blocks the UI to respond:

this.KeyPress += Form1_KeyPressed;
....
private async void Form1_KeyPressed(object sender, EventArgs e)
{
   for(int i=0; i<int.max; i++)
      ;
}

What am I missing in Eric's answer?

like image 275
Hans Avatar asked Aug 26 '26 11:08

Hans


2 Answers

What am I missing in Eric's answer?

I meant that it works like any other asynchronous method. When you await something in an asynchronous method the remainder of the method is signed up as the continuation of the awaited thing. That is true whether the asynchronous method is void or not.

In your example your code works exactly like an asynchronous method that returns a task. Try changing your method to return a task, and you'll see it behaves exactly the same.

Remember, "async" does not mean "I run concurrently on another thread". It means "the method may return before its action is completed". The points at which it may return before its action is completed are marked with "await". You haven't marked anything with "await".

I suspect you believe the myth that asynchrony requires concurrency. Again: asynchrony simply means that a method can return before its work is done. You start cooking some eggs, the doorbell rings, you go get the package off the porch, you finish cooking the eggs, you open the package. The "cook eggs" and "fetch the mail" jobs are not concurrent -- you never did them at the same time. They are asynchronous.

like image 126
Eric Lippert Avatar answered Aug 28 '26 00:08

Eric Lippert


All the async keyword does is allow you to await an asynchronous operation in your method (and wraps the result in a task).

Every async method runs synchronously until the first await is reached. If you don't await anything then this method (whether it returns a task or doesn't) will run synchronously.

If your method is synchronous you usually don't need to use async await at all. But if you want to offload a CPU intensive operation to a different thread so the UI thread wouldn't be blocked for a long time you can use Task.Run:

await Task.Run(() => CPUIntensiveMethod());
like image 40
i3arnon Avatar answered Aug 28 '26 01:08

i3arnon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!