Stumbled upon this post that talks about making async web requests.
Now simplicity aside, if in real world, all you do is make an async request and wait for it in the very next line, isn't that the same as making a sync call in the first place?
-
8Not exactly. Your code is synchronous in a sense that nothing happens until you get a result. However underneath, you probably gave up the thread you were running on until the async method returned, then got assigned another thread to continue executing.Roman– Roman2013年01月14日 16:31:22 +00:00Commented Jan 14, 2013 at 16:31
-
2it is but with async you can do another async at the same time and then await the 2, with sync this is not possibleratchet freak– ratchet freak2013年01月14日 16:32:10 +00:00Commented Jan 14, 2013 at 16:32
-
Here's an article (tomasp.net/blog/async-compilation-internals.aspx) discussing some of the under-the-hood of async in C# -- it's part of a series covering asynchronous programming in C# and F#.paul– paul2013年01月14日 16:49:01 +00:00Commented Jan 14, 2013 at 16:49
-
@ratchetfreak: Yes, that goes without saying if you're doing multiple calls.Mrchief– Mrchief2013年01月14日 19:09:52 +00:00Commented Jan 14, 2013 at 19:09
-
@R0MANARMY: If your app is doing other things, then yes and async + await enables that. Akim says it best! But imagine the code not being in button_click handler, or any such event handler for that matter. If someone blindly copies the code (async+await lines), to any method, it can lead to fals impression that your code is async but in effect may not be.Mrchief– Mrchief2013年01月14日 19:12:39 +00:00Commented Jan 14, 2013 at 19:12
5 Answers 5
No, async + await != sync
, because of continuation
From MSDN 'Asynchronous Programming with Async and Await (C# and Visual Basic)'
Async methods are intended to be non-blocking operations. An await expression in an async method doesn’t block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method.
For example async execution will not block UI thread, and Some TextBox.Text
will be updated after download has finished
private async void OnButtonClick()
{
SomeTextBox.Text = await new WebClient().DownloadStringTaskAsync("http://stackoverflow.com/");
}
-
1
-
1Could you explain in more detail. Are you saying... that without this... you would not be able to interact with the UI... as this would be on the main thread. So does this mean that this only become applicable in a application type program apposed to web where interaction is separate from the web server thread. So in a nut shell this only become important i.e. not sync* when your main thread is the running thread. Wouldn't this create unexpected behavior, i.e. in a App(1 main thread) two buttons clicked.. but you should be able to click the 1 without the first completing?Seabizkit– Seabizkit2016年12月07日 09:38:36 +00:00Commented Dec 7, 2016 at 9:38
-
What about
Console.WriteLine(await GetStringOverNetwork());
? What if you need the output of the asynchronous invocation? Would the program block on first access, even if the thread could potentially continue execution?Andrew– Andrew2018年11月05日 04:01:01 +00:00Commented Nov 5, 2018 at 4:01 -
@Seabizkit whatever calls you
await + async
has the opportunity to do other stuff in the mean time. If you should only be able to click one button at a time, then you need to disable the other button before the firstawait
Caleth– Caleth2020年07月30日 09:24:26 +00:00Commented Jul 30, 2020 at 9:24 -
@Caleth this was posted in 2016, i have a much much better understanding now. reading stuff like this now, in retrospect is difficult as i don't know what i did and didn't know then... but have it all down like a boss in the +-4 years since ;-)Seabizkit– Seabizkit2020年07月30日 10:03:43 +00:00Commented Jul 30, 2020 at 10:03
No it's not the same.
Your async
code block is waiting for the await
call to return to continue, however the rest of your application isn't waiting and can still continue like normal.
In contrast, a synchronous call would make your entire application or thread wait until the code finished executing to continue on with anything else.
-
couldn't the sync call be implemented as async+await?ratchet freak– ratchet freak2013年01月14日 16:35:30 +00:00Commented Jan 14, 2013 at 16:35
-
@ratchetfreak I think there's some overhead to setting up await/async, so I don't think you'd want to code your entire application with it. I only use it for executing potentially long-running blocks of code so it doesn't lock up my applications. :)Rachel– Rachel2013年01月14日 16:39:50 +00:00Commented Jan 14, 2013 at 16:39
Please allow me to clarify things in regards to async/await.
When await is encountered the underlying state machine allows control to be returned immediately. Then, when the awaited call is completed, the underlying state machine allows execution to resume at the line after the awaited call.
Therefore, the async block is not blocked nor is it waiting for the awaited call to finish; Control is returned immediately when the await command is encountered.
The underlying state machine is part of the "magic" behind the use of async/await that is not disused and missed.
I stumbled on this with the same question in mind, yet after reading the responses the question seems to linger, confused by references to "magic under the hood".
From the above-mentioned Asynchronous Programming :
- The
async
keyword turns a method into an async method, which allows you to use theawait
keyword in its body.- When the
await
keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete.await
can only be used inside anasync
method.
Does the context that encounters await
get blocked?
- Yes. That's essentially a local sync barrier to maintain a known state in the context of the execution; except that other contexts, if any, are not joined.
Does the rest of the application block at the await
?
It depends on how your application is written. If it's a series of dependent
await
ed tasks launched sequentially in the same context (see: Trying to understand some async/await behavior)await asyncCall1(); await asyncCall2(); // waits for asyncCall1() to complete
this way each
await
would block spawning of the next one.On the other hand, the same dependent tasks launched in parallel would execute in parallel and the context would only block at the resp.
await
:Task<int> t1 = asyncCall1(); Task<string> t2 = asyncCall2(); // runs in parallel with asyncCall1() int val = await t1; string str = await t2; // waits for asyncCall1() to complete
In general, the
await
yields execution to the outer context, from where the current context is called. However, if the outer context itself is awaiting for the current, then it's like a sequentialawait
s in the same context.
So, to reap the async
benefits, one needs to design the application to run several parallel contexts (UI, data-client etc.), then await
in one context yields execution to other contexts, so the whole application would not block on an individual await
.
async + await don't just make an asynchronous call and wait for the result to be delivered, that would indeed be synchronous. That would happen if you created a semaphore, launched a new pthread for example that signals the semaphore when it is finished, and then wait on the semaphore. But async + await as part of the language is different.
What it does is basically creating a new thread to run the "async" task, passes the "await" code to it as a continuation (which is comparable to a "clever" function pointer),and when the task finished, it calls the "await" code. In other languages, like Objective-C or Swift, that's actually how you achieve the same effect. And all that is asynchronous.