Click here to Skip to main content
15,881,172 members
Articles / Web Development / ASP.NET / ASP.NETvNext
Tip/Trick

From Task to Async/Await

Rate me:
Please Sign up or sign in to vote.
4.32/5 (9 votes)
17 Jan 2016CPOL5 min read 22.3K   536   18   5
Use of Task Parallel Library and Async/Await in your application

Introduction

If you are one of those who often wonder about what that much talked about Task Parallel Library in .NET does or if you ever wondered what should be the perfect scenario in your application to implement Async/Await, then this tip is for you. I have struggled with Async Await and TPL in my initial days, then I slowly gained the experience to see how it fits into my application.

In this tip, we are going to discuss about Task Parallel Library (a.k.a TPL) of .NET and slowly refactor our code to implement async/await. By the end of this tip, our aim will be to gain knowledge about where and how we should be using TPL/async-await/Continuation, etc. in our application. We are going to take a demo driven route.

P.S.: Start with the TPLDemo_UnresponsiveApp.zip. The completed solution is there in TPLDemo.zip.

Background

.NET Framework has evolved a lot from its classic Thread based approach to Task based approach. Making responsive application has become much easier. At first, let's take a look into what a unresponsive application is.

Please download the zipped file named - TPLDemo_UnresponsiveApp.zip. In that demo, we have written a simple XAML page with two TextBoxes for UserName and Password also there is one Login button.

Please run the application in Visual Studio (preferred version 2013). If you click on the Login Button and then click anywhere in the app, you will find that the app freezes up for 10 secs. The reason is we have spinned up a thread at the time of clicking the button, and that particular thread has made the UI unresponsive because it has blocked the UI thread. In this approach, we are trying to simulate what would happen to our application in case of a slow DB/Network call.

C#
private void LogInButton_Click(object sender, RoutedEventArgs e)
{
   Thread.Sleep(10000);
}

Now, our aim would be to make our application responsive and at the same time, it should feel like it runs much faster.

Introducing Task Parallel Library

To make this application responsive, we are going to implement Task Parallel Library. TPL was introduced in .NET 4.0 to execute concurrent as well as asynchronous code. Just remember one simple tip.

"Task represents an asynchronous operation."

So in our solution, we are going to take the following piece of code and run that as an asynchronous Task.

C#
Thread.Sleep(10000);

To run it as a Task, we need to do two things:

  1. Import System.Threading.Tasks namespace;
    C#
    using System.Threading.Tasks;
  2. Put our statement as a Task.
    C#
    Task.Run(() => { Thread.Sleep(10000); }); 

If you are done till this point, then Congratulations - you have run your piece of code asynchronously. In this case, the method inside the braces have waited for 10 secs but it is not blocking UI thread so your application will behave in a proper responsive way.

You can now click on the Login button and check whether your app is responsive or not.

Going Deeper into Task Parallel Library

Now coming into a more practical requirement.

#Requirement 1: After the Task finishes, suppose you want to display a message or do any other custom action.

Solution: To schedule something to be executed once a Task is finished, we use "continuation". Task.Run( ) returns a Task Handler, we could make use of that and set up continuation.

Let's get our hands dirty with some code.

Replace the following code with:

C#
Task.Run(() => { Thread.Sleep(10000); }); 

This:

C#
var task = Task.Run(() => { Thread.Sleep(10000); });

Now, we will be able to apply continuation which will allow us to create a Task which will run asynchronously once the Target task completes.

C#
task.ContinueWith((t) => {
                MessageBox.Show("Simulation completed");
            });

#Requirement 2: Once the background simulation starts, you want to disable the Login Button and once it's completed, you want to enable the login button.

So we are going to disable the login button first and then enable it. We have the code snippet in one go. I think it is pretty much self explanatory.

C#
LoginButton.IsEnabled = false;
var task = Task.Run(() =>{
Thread.Sleep(10000);});

task.ContinueWith((t) => {
MessageBox.Show("Simulation Completed");
Dispatcher.Invoke(()=>{
LoginButton.IsEnabled = true; 
   });
});

The only catch in the above code is the placement of IsEnabled property. We have to keep in mind LoginButton is a part of UI main thread so to access any property of that button, you have to be in UI thread. That is why in continuation we have to use Dispatcher.Invoke() to return to UI thread. You can read more about it in this link.

Introducing Async/Await

Now, we will be refactoring our above code to use Async/Await.

First things first: We need to tell the compiler that our method is capable of running asynchronous code. So we will mark our method as async.

C#
private async void LogInButton_Click(object sender, RoutedEventArgs e)

So, in the previous demo, we started a simulation which runs for 10 secs under Task.Run(). While it runs, we keep our LoginButton disabled. Once the simulation completes, we display a message to the user also we do enable to LoginButton as well.

Point to note: Marking a method Async doesn't really directly run all your code asynchronously.

C#
LoginButton.IsEnabled = false;
Task.Run(() =>
            {
                Thread.Sleep(10000);
            });

Our aim is to run the continuation after this. So to tell the compiler to stop the execution in this part, we are going to introduce await keyword.

Await keyword will be applied to the part of our code which we want to Await till the next executable statement comes into play.

C#
LoginButton.IsEnabled = false;
await Task.Run(() =>
            {
                Thread.Sleep(10000);
            });
C#
MessageBox.Show("Simulation completed");
            LoginButton.IsEnabled = true;

So, the second part of the code will run only after complete execution of the await statement code.

Thus, Async/Await makes our life much easier whilst using Task.Run() or Task Parallel Library.

Points of Interest

Using task parallel library along with Async/Await will be best way leverage Asynchronous programming in C#. Sometimes, we need to train your mind really sharp to know what is happening in the background of TPL or Async/Await. But once you do, it's really rewarding.

History

.NET has evolved a lot from Thread to Task to Async.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
.NET developer with close proximity to Mobile Technology(Xamarin/Windows Phone). Also passionate about ASP.NET MVC/WebApi development

Comments and Discussions

 
Questionnew thread vs async Pin
Gulshan Grover17-Jan-16 15:40
Gulshan Grover17-Jan-16 15:40 
Async await does not create a new thread unlike TPL approach but rather yields the current thread to provide responsiveness. Correct ? I am not sure myself. I will google for this to find more info. Your tip is helpful syntaxically. I am trying to found out how it works under the hood..Thanks
AnswerRe: new thread vs async Pin
SubhamoyBurman17-Jan-16 21:15
professionalSubhamoyBurman17-Jan-16 21:15 
GeneralRe: new thread vs async Pin
William E. Kempf25-Jan-16 6:44
William E. Kempf25-Jan-16 6:44 
QuestionA couple of suggestions Pin
George Swan17-Jan-16 11:49
mveGeorge Swan17-Jan-16 11:49 
AnswerRe: A couple of suggestions Pin
SubhamoyBurman17-Jan-16 21:16
professionalSubhamoyBurman17-Jan-16 21:16 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.