*Asynchronous Programming :
Introduction to async programming with .NET
Asynchronous Programming is an interesting topic, but sometimes a confusing topic to wrap your head around. So let's start with an analogy. Traditional synchronous, or non-asynchronous, programming is like deciding to build a house.
You start with a foundation, then build a frame, plumbing, electrical and so on. Even with a small house, it might take you years to do it yourself. On the other hand, asynchronous programming is like deciding to build a house, but instead of doing it all yourself, you decide to hire a contractor to do the foundation.
Another contractor to do the frame. Another for plumbing, etC. So that they all try to do as much work at the same time, whenever possible. While they are working, you are also free to do other things, such as project manage, for example, therefore, overall you are able to get the job done in maybe just a few months instead of years
Let's imagine we are writing an application that has a user interface that needs to remain responsive.Our application also needs to download a large file. So, let's create a function that simulates downloading this large file.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Downloading file");
//. The line after that causes our program to freeze up, while the simulated download takes place
Download();
Console.ReadLine();
}
static void Download()
{
Thread.Sleep(4000);
Console.WriteLine("Download Complete");
}
}
Note :We have used Download() method to pause the application for three seconds. And, since it takes milliseconds, I'll pass in 4,000.This will simulate the application becoming unresponsive and the interface locking up. Since it's a console application it will make the console interface unresponsive and we won't be able to type into it.
If we run this now, and I try to type within the three seconds when the file is downloading it will be unresponsive and you won't see the characters I've typed in.
So, if this was an application with a graphic user interface, the buttons and inputs would become unresponsive at this point. The program never gets to make it here until the three seconds are up. So, lets try to solve this issue now with asynchronous programming.
Tasks:
- .Net has some built-in functionality to help with this called Tasks.
You can think of it as multiple people reading or going through your app line by line at the same time. So, when one is busy downloading, the other can continue to read and handle any console input in our case. And, so, our user interface remains responsive, even though part of the app is busy with the download.
-A task represents a single asynchronous operation that does not return a value. Task objects are one of the central components of the task-based asynchronous pattern introduced in .Net 4.
-Creating and starting a task can be done in many ways. But, with .Net 4.5, a very simple and effective method was introduced. The Run method. It allows us to just start a task with default values, without having to do any set up or provide any additional parameters.
- Let's continue and wrap our Thread Sleep and console right line with a Task.Run
Task.Run(() => {
Thread.Sleep(4000);
// simulated download is complete
Console.WriteLine("Download Complete");
}
);
This will allow us to run it asynchronously. It essentially allows me to create an inline anonymous function. So, everything you see in these braces is a function without a name. And the function has been embedded in the parameter of Task.Run.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Downloading file");
//download simulation
Download();
// to simulate our interface being responsive by being able to type into it.
Console.ReadLine();
}
static void Download()
{
//At that point .Net realizes it's time to hire someone else
//to do this job so that I can keep going and so that this
//thread is now reading through the lines instead of .Net.
//So, the new helper gets to Thread.Sleep at this point, and
//takes a break for three seconds. Meanwhile,
//.Net has skipped past this and is now on Console.ReadLine
Task.Run(() => {
Thread.Sleep(4000);
// simulated download is complete
Console.WriteLine("Download Complete");
}
);
}
}
Note : As you can see, We can type while the file is downloading and when the download is complete we also can see the Download Complete message.So, we're able to download the file and type and do both things asynchronously.
Asynchronous programming is great when working with tasks that take time such as reading files from the disc, working with databases, or communicating over the network. That's why you see modern web frameworks all use asynchronous programming.
Async and Await keyword : to manage program flow
-The Async and the Await keyboards can help us even further with the problem we faced and solved in above downloading problem.
In this project, we have a mock or imaginary network library, and just in like in our Asynchronous program, it runs asynchronously, and we are able to download while still being able to type in the console.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Downloading file");
//This line causes our program to freeze up,
//while the simulated download takes place
Download();
// to simulate our interface being responsive by being able to type into it.
Console.ReadLine();
}
static void Download()
{
Network.Download(); //It simply goes down, do not return
//in this case this line passes without waiting for
//complete download the file.or it does not take 4 seconds to disply
//this message
Console.WriteLine("Download complete");
}
}
//a mock or imaginary network library.
class Network
{
static public Task Download()
{
return Task.Run(() => Thread.Sleep(4000));
}
}
Note : In this, we were never notified when the actual download was complete.
To do this, we'll need to use Await, which will return the flow of the program to the Await line when the execution of the task it's waiting on is complete. So let's add Await in front of the network download now, and once we get this working, the execution flow will return to the next line , and display a message that says actual "Download Complete".
static void Download()
{
await Network.Download(); //It simply goes down, do not return
//in this case this line passes without waiting for
//complete download the file.
Console.WriteLine("Download complete");
}
In this case it gives the error saying , await operation can only be used with aync method. so make download method async.
static async void Download()
{
await Network.Download(); //It simply goes down, do not return
//in this case this line passes without waiting for
//complete download the file.
Console.WriteLine("Download complete");
}
Full program :
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Downloading file");
Download();
// to simulate our interface being responsive by being able to type into it.
Console.ReadLine();
}
static async void Download()
{
await Network.Download();
//This line will be executed after 4 seonds
Console.WriteLine("Download complete");
}
}
//a mock or imaginary network library.
class Network
{
static public Task Download()
{
return Task.Run(() => Thread.Sleep(4000));
}
}
-There are many .NET libraries that have Asynchronous functions built in. Let's take a look at one now and download something instead of faking it with our network class.
Now instead of using Network.Download, we'll use our new client with .GetStringAsync and we'll need to pass in a URL.
Note : It is just a one example of working with an Asynchronous.NET function and there are many more, whether we are working with processing images, file access, database or network access.
Anonymous functions, callbacks, and action to manage program flow :
- We will begin by comparing anonymous functions with callbacks and seeing how they differ. We need to figure out here how to get a notification that our download is complete.
- This time instead of using async and await, we will use both callbacks and eventually inline anonymous functions.
Let's begin by converting our download function into a callback function. To do that, we will need to use the action keyword. That allows us to pass and functions as delegates, which are essentially references to a method that we can pass as a parameter.
we used the action keyword. That allows us to pass and functions as delegates, which are essentially references to a method that we can pass as a parameter.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Downloading file");
//while the simulated download takes place
Download();
// to simulate our interface being responsive by being able to type into it.
Console.ReadLine();
}
static void Download()
{
Network.Download(DownloadComplete); //passing reference to DownloadComplete() function as a parameter to our network download method.
}
//executes after download complete : callback function
static void DownloadComplete()
{
Console.WriteLine("Download complete");
}
}
//a mock or imaginary network library.
class Network
{
static public Task Download(Action callback)
{
return Task.Run(() =>
{
Thread.Sleep(4000);
//implemented an actual callback function
//that passed as a delegate to Download function.
callback();
});
}
}
Implement Download method with annomous function:
static void Download()
{
Network.Download(() => Console.WriteLine("Download Complete"); //passing reference to DownloadComplete() function as a parameter to our network download method.
}
Still to receive the custom message as a parameter form callback method :
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Downloading file");
//while the simulated download takes place
Download();
// to simulate our interface being responsive by being able to type into it.
Console.ReadLine();
}
static void Download()
{
Network.Download((message) => Console.WriteLine(message); //passing reference to DownloadComplete() function as a parameter to our network download method.
}
}
//a mock or imaginary network library.
class Network
{
static public Task Download(Action
{
return Task.Run(() =>
{
Thread.Sleep(4000);
//implemented an actual callback function
//that passed as a delegate to Download function.
callback("Downloaded");
});
}
}
Here,
First : We modified the Network Download, action to use its generic form and pass a string as a type. That encapsulates a method that has a single parameter and does not return a value.
static public Task Download(Action
Second :
callback("Downloaded"); , we call the callback with custom message.
Third :
Change this lamda expression to receive the parameter called message.
Network.Download((message) => Console.WriteLine(message);
Main Points :
Although async and await is the most modern way to work with asynchronous code and to make your code look clean, callbacks, lambda expressions, and anonymous functions are also great additions that you can use in combination to achieve modern, clean code standards.
Comments
Post a Comment