Asynchronous programming is a form of concurrent programming that enables the execution of several tasks at once. It enables you to carry out multiple jobs at once. In certain ways, it is non-blocking.
Making your code run asynchronously makes your application more receptive to user input, and by running your Tasks concurrently (we’ll cover tasks in more detail later on in the blog), the code block executes much more quickly than with synchronous programming, improving the performance of your application.
asynchronous programming was made available in.net version 1.1.
Prior to the introduction of the three magical keywords from c# 5.0 async await Tasks, c# was initially asynchronous but c# developers did not choose to design their application asynchronously due to the lengthy and complex programming.
In a manner, the tables were turned because these keywords made asynchronous programming much less time-consuming and challenging.
async/await: These two keywords together allow you to run your code asynchronously and without blocking your code.
The Async keyword needs to be added to your method in order for your code block to be executed asynchronously.
The use of async & await enhances your application’s overall usability.
It forces the concurrent asynchronous execution of your synchronous code style.
Your app becomes more responsive as a result.
Most critically, thread pool starvation is avoided. (Or, don’t worry about it too much; we’ll talk about it when we see about Tasks more briefly.)
When the compiler encounters the phrase async, it denotes a waitable method that can be called asynchronously by using the await keyword. And when the compiler encounters the phrase await, it performs a magic trick and goes back to the method that was invoked with await.
Although the main thread is not blocked when the keyword await is used, it does indicate that the application will not respond until the async method’s task has completed and been returned.
When you use async/await to run a piece of code asynchronously, it should always return a type of Task ie, which will be covered in the blog post that follows.
Here is an example of asynchronous programming in C# using the async and await keywords:
In this example, the Main method calls the AsyncMethod asynchronously and waits for it to complete using the await keyword. The AsyncMethod runs some code asynchronously using a task, and then returns the result using the return keyword.
The async keyword indicates that a method contains asynchrony, and the await keyword is used to wait for a task to complete before continuing. In this case, the await keyword is used to wait for the task created with Task.Run to complete before returning the result.
Here is how the code executes: Main method is called and starts executing.
Step 1: The AsyncMethod is called asynchronously using the await keyword.
Step 2: The AsyncMethod creates a task using Task.Run and runs some code asynchronously. In this case, the code simply sleeps for 2 seconds.
Step 3: The AsyncMethod waits for the task to complete using the await keyword.
Step 4: The task completes and the AsyncMethod returns the result 42.
Step 5: The Main method continues execution and prints the result to the console.
Using asynchronous programming, we were able to run the long-running task concurrently with the rest of the program, rather than blocking the main thread and making the program unresponsive. This can improve the performance and responsiveness of our program, especially when working with external resources like databases or web services.
Task is a crucial component of asynchronous programming in c#. Dot Net Framework provides Threading.Tasks class to let developers to create and run Task-based asynchronous Programming and was introduced with the .NET Framework 4.0.To create an object that represents work that should be completed asynchronously, use the task class. Instead of running synchronously on the application’s main thread, it is typically executed on a thread pool, or group of threads.
Working of Task:
Task maintains each task i.e. work that need be done in a task queue which then executed the each task asynchronously in a thread pool based on the availability of the thread. Then it maintains another queue to store the result of the completed task and returned back.
Generally, task are used for CPU Bound operations like heavy calculations, looping through an array which involves use of CPU capabilities and it is not suitable for IO bound work. The reason why it is not advised to use task for IO operations is that’s because your I/O bound workload is throttled by the capabilities of your storage device. No matter what you do with code, the hardware has a limit on how many data can store or retrieve per time-unit. So, the thread assigned for the task waits till the IO operation is completed.
In this example, we create two tasks using the Task.Run method and start them concurrently. The tasks simply print a message to the console and sleep for a certain number of seconds.
We can then use the WaitAll() method to block the main thread until all tasks have been completed. After both tasks have completed, a message is printed to the console indicating that all tasks have completed.
The order in which the output results will be printed are:
Task 1 is running.
Task 2 is running.
All tasks have completed.
This demonstrates how tasks can be used to perform multiple tasks concurrently, rather than sequentially. By using tasks, we can improve the performance and responsiveness of our program by allowing it to perform multiple tasks at the same time.
In conclusion, asynchronous programming is a useful programming paradigm that allows a program to perform multiple tasks concurrently, rather than sequentially. It can improve the performance and responsiveness of a program by allowing it to continue executing while waiting for long-running tasks to complete. In C#, asynchronous programming can be implemented using tasks and the async and await keywords. By using asynchronous programming, developers can write scalable and maintainable code that can make the most of modern hardware and improve the user experience of their programs.