I am trying to understand asynchronous programming and came across async/await keywords. I got stuck in understanding use of async/await keywords. I actually looked in two programming languages, JavaScript and C# and found much differences in use of async/await keywords in both languages.
For JavaScript it says:
Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. The await keyword blocks execution of all the code that follows it until the promise fulfills, exactly as it would with a synchronous operation.
Link: https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await#:~:text=Async%2Fawait%20makes%20your%20code,would%20with%20a%20synchronous%20operation.
So, its saying that async/await will make the execution synchronous.
For C# it says:
The async keyword turns a method into an async method, which allows you to use the await 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.
Link: https://learn.microsoft.com/en-us/dotnet/csharp/async#:~:text=The%20async%20keyword%20turns%20a,used%20inside%20an%20async%20method.
So, its saying that use of async/await will make the code execution asynchronous.
I would like to ask, is there really a difference between the use of async/await keywords in JavaScript and C#?
Or,
Is something missing in above statements?
One difference is that Node. js is asynchronously single-threaded, while ASP.NET is asynchronously multi-threaded. This means the Node. js code can make some simplifying assumptions, because all your code always runs on the same exact thread.
The await operator is used to wait for a Promise . It can only be used inside an async function within regular JavaScript code; however it can be used on its own with JavaScript modules.
The async keyword is used to define an asynchronous function, which returns a AsyncFunction object. The await keyword is used to pause async function execution until a Promise is fulfilled, that is resolved or rejected, and to resume execution of the async function after fulfillment.
Async/Await makes it easier to write promises. The keyword 'async' before a function makes the function return a promise, always. And the keyword await is used inside async functions, which makes the program wait until the Promise resolves.
In terms of behavior there's no difference between javascript and c# in async/await. async keyword denotes that there's an asynchronous operation in this method. await keyword helps making a CPS (continuation passing style) coding into a code that looks like synchronous.
An async function is a function that is declared with the async keyword and allows the await keyword inside it. The async and await keywords allow asynchronous, promise-based behavior to be written more easily and avoid configured promise chains.
Await function is used to wait for the promise. It could be used within the async block only. It makes the code wait until the promise returns a result. It only makes the async block wait. Notice that the console prints 2 before the “Hello World”. This is due to the usage of the await keyword.
If we try to use await in a non-async function, there would be a syntax error: function f() { let promise = Promise.resolve(1); let result = await promise; // Syntax error } We may get this error if we forget to put async before a function. As stated earlier, await only works inside an async function.
Javascript docs says 'it makes your code look synchronous', it doesn't say 'it makes your code synchronous'.
In terms of behavior there's no difference between javascript and c# in async/await.
async keyword denotes that there's an asynchronous operation in this method. await keyword helps making a CPS (continuation passing style) coding into a code that looks like synchronous. CPS is similar to using then() in javascript after promises or using ContinueWith() in C# Tasks.
Any code before 'await' is running synchronously under current thread. When execution reaches to 'await', the awaited operation starts under a new thread (not necessarily a new thread, but suppose a new thread), hence an asynchronous operation starts, and current thread is freed. When the awaited operation ends, execution returns to the point it left off in the 'await' keyword and continues.
The internal working of javascript and C# are different.
Javascript is event-driven. There is a main event loop and a single thread in javascript. When the awaited operation finishes, an event is raised under the hood and the main single thread continues executing of the async function where it was left off.
In C# there's no event loop or a single thread. We either should use manual threads and explicitly wait and join them after they did their job, or we should use something like async/await that manages thread and continuation management on behalf of us. Using TPL which C#'s async/await internally uses that, continuation of an async code is passed to another task using callbacks.
Anyhow, 'await' keywrods turns a complicated chain of nested then() -js- or ContinueWith() - c#- into a simple beautiful code that looks like a normal -synchronous- code.
function doSomethingCPS() {
asyncOperation1()
.then(r1 => { consume(r1); return asyncOperation2() })
.then(r2 => { consume(r2); return asyncOperation3() })
.then(r3 => { consume(r3); })
}
async function doSomethingAsync() {
var r1 = await asyncOperation1();
consume(r1);
var r2 = await asyncOperation2();
consume(r2);
var r3 = await asyncOperation3();
consume(r3);
}
The two codes are equivalent. But, it's clear that the latter is much more simpler and easier to read.
There's a difference between thread management in javascript and c#.
As it is said, in javascript there's only one thread. If it blocks for any reason, the page will block. It's when browsers show 'The page is not responding' or 'There is a javascript code in this page that blocks the page' message after 20-30 seconds.
In HTML5 worker threads were introduced that helps to employ a real separate thread. It's another topic though.
You might ask if there's only one thread in javascript, how on earth can an asynchronous operation work that is said to work under another thread?!
Good question. In javascript although there's only one single thread, there are objects that natively use separate threads. timers - setInterval() and setTimeout()-, XMLHttpObject() and fetch() are good examples in this regard. Thus, in javascript we indeed can have asynchronous code.
One final point is the way C# uses threads. In C#, async/await works using a library named TPL (Task Parallel Library). There is a Task class at the heart of TPL that resembles an asynchronous task.
The real point we should know is that, a Task is equivalent to an async operation, but it does not necessarily mean a Task uses explicitly a separate thread. There's a task scheduler in TPL that controls internal threads usage. If a Task's job is quick, using a separate thread wastes resources, so the task will run under current thread.
The only thing we should know is that a Task is a logical unit of asynchronous code. In fat, Task is introduced to free us of manually thread management which is nearly a low-level code.
Using async/await we are rid of all boilerplate code that are required under the hood to provide asynchronous code. We can focus on our business code instead.
I am not familiar with JavaScript but this statement:
Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. The await keyword blocks execution of all the code that follows it until the promise fulfills, exactly as it would with a synchronous operation.
Sounds pretty much applicable to C# async/await. For both cases your code looks like you execute it synchronously and your execution is sequential. Because in C# when you have code like this:
// ...
await FooAsync();
Console.WriteLine("Await has returned the execution");
It seems as if your execution thread were running FooAsync
, and then, the same thread is calling Console.WriteLine
. Whereas in reality when the execution thread hits await
, it does lots of things behind the scene. Here's a good article about it. But in most of the cases,
When the await keyword is applied, it suspends the calling method and yields control back to its caller until the awaited task is complete.
The thread that were executing your code will go about his business. And then proceed with Console.WriteLine
when FooAsync
is complete by another (or the same) thread.
This behavior is enormously helpful when you work with UI threads like in WPF or WinForms applications.
For example, FooAsync
is a very heavy method. It does lots of calculations and takes a lot of time to complete. But you're running your code on UI and when a user hits a button, the underlying code is executed by the UI thread. So if you'll be running and waiting FooAsync
synchronously like this:
FooAsync().Result;
Your UI would be "freezed" and the user would demise you. So when you go
await FooAsync();
UI thread "asks" TaskScheduler to run FooAsync
by whatever available thread. After the Task is completed, TaskScheduler tries to execute next line:
Console.WriteLine("Await has returned the execution");
by the UI thread again,
exactly as it would with a synchronous operation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With