Asynchronous Programming using Async Await in C#

Before C# 5, trying to write asynchronous code was difficult. It was hard to read and tricky to debug. Thankfully Microsoft have added the Async and Await keywords to make asynchronous programming far more manageable, but there is still a lot of uncertainty in the .NET development community on how this works so let’s have a look at some coded examples.

Async Await is all about Tasks

When programming asynchronously it’s important to understand that its all about Tasks. When creating an async method the return type is a of Task or Task<T>. The difference between these two types is simple. If your async method is void with no return type, then you would set this to return Task. If your async method is non-void and returns any type of value then you would return Task<T> where T is the type you want to return.

Now you may be thinking, what's the difference between Asynchronous Programming and Multithreaded Programming?

So, like I said before Async is about Tasks. Multireading is all about Workers

Understanding the differences between Async and MultiThreaded

Asynchronous Programming (Multithreaded)
you hire 2 employees, 1 to fill your car with fuel and the other to wash your car. However, as they are running asynchronously you will need to direct them so they can work without interfering with each other and manage any shared resources.

Synchronous Programming (Single Thread)
you fill up the car and then wash the car.

Asynchronous Programming (Single Thread)
you set the fuel pump to begin filling the car and while that is in progress you start to wash the car. When the fuel tank is full the pump will notify its complete. You take out the pump and then finish washing the car.

Synchronous Programming (Multithreaded)
you hire 2 employees, 1 to fill your car with fuel and the other to wash your car. They are working completely independent of each other and will complete when they are done.

So now you understand the principles let’s explore in more detail the two new keywords Async and Await.

Async Keyword.

Assigned to a method signature, this tells the compiler that it’s an async method and Visual studio will allow you to add the await keyword within the method. Without making a method as async, you cannot add the await keyword as your code will not compile.  You can also call await on any method marked as async.

public async void BeginLongOperation()

Await Keyword.

The await keyword will stop operation until the current line of code competes. It does this by executing the current line and then at the same time transferring operation back to the calling method so it can continue its execution. This is the key aspect of using Async Await in C#.

Let’s have a look at some code. The example is a console app that will call an async method and while that is executing it will continue to loop outputting Asterisks to the console until the async method completes.

public async void BeginLongOperation()
{
    _IsOperationComplete = false;
    Console.WriteLine("Begin Start LongOperation() - Please Wait " + Environment.NewLine);

    int RandomNumber = await LongOperation();

    Console.WriteLine(Environment.NewLine + "Finish End LongOperation() Async Return Int = " + RandomNumber);
    _IsOperationComplete = true;
}

This is our async method, we are calling await on LongOperation() this means that it will execute this method while at the same time passing back to the original call for that to continue. Let’s have a look at the method LongOperation() in more detail.

private Task<int> LongOperation()
{
    return Task.Run(() => {
        Console.WriteLine($"Executing LongOperation - Sleep Duration = {_SleepDurationSeconds}");
        Thread.Sleep(_SleepDurationSeconds);

        return new Random().Next();
    });
}

This is the method we call await on. You can see that it has a return type of Task<int> this means that we are returning a task object that will itself will return an int. Interestingly you can see that we have 2 return statements in a single method. For the example I am simply returning a random number for the int, but in a real application this could be any type of object. Task is generic with the signature Task<T>.

Let’s have a look at the full code.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace AsyncProgrammingExample
{
    public class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("Program start " + Environment.NewLine);

            AsyncTask worker = new AsyncTask(1);
            worker.BeginLongOperation();

            while(worker._IsOperationComplete == false)
            {
                Thread.Sleep(50);
                Console.Write("*");
                Thread.Sleep(50);
            }

            Console.WriteLine("Program complete");
            Console.ReadKey();
        }
    }

    public class AsyncTask
    {
        public bool _IsOperationComplete { get; private set; }

        public int _SleepDurationSeconds { get; private set; }

        public AsyncTask(int DurationSeconds)
        {
            _SleepDurationSeconds = (DurationSeconds * 1000);
        }

        public async void BeginLongOperation()
        {
            _IsOperationComplete = false;
            Console.WriteLine("Begin Start LongOperation() - Please Wait " + Environment.NewLine);

            // - as we have called await - this method cannot continue until LongOperation() 
            // has completed. the call is passed back to the calling method - the while loop
            int RandomNumber = await LongOperation();

            Console.WriteLine(Environment.NewLine + "Finish End LongOperation() Async Return Int = " + RandomNumber);
            _IsOperationComplete = true;
        }

        private Task<int> LongOperation()
        {
            return Task.Run(() => {
                Console.WriteLine($"Executing LongOperation - Sleep Duration = {_SleepDurationSeconds}");
                Thread.Sleep(_SleepDurationSeconds);

                return new Random().Next();
            });
        }
    }
}

Following through the code it’s important to know that this is a console app and the starting method is Main. To begin the application starts by outputting “Program Start” to the console and then creates an instance of the class AsyncTask passing a value of 1 for 1 second into the constructor. Next it calls the method BeginLongOperation() this executes until it reaches the await keyword, execution is passed back to the main method where it now enters the while loop. The boolean prioperty _IsOperationComplete is set a false and will remain false until LongOperation() completes. Asterisks are logged during iteration of the loop. As soon as LongOperation() completes the property is set to true and the while loop breaks which then completes the program.

So there we have it, a simple example of how to code asynchronously in C# using Async Await. Please have a play with the code above and try using Async Await on your C# project. Please leave your thoughts in the comments.


JGilmartin Profile Image

JGilmartin

Technical Architect at Pinewood Technologies

Rating: 2890

C# Expert

Offline


Tutorial Statistics
  • Views: 1084
  • Comments: 0
  • Author: JGilmartin (2890)
  • Date: 5/6/2017 22:13
Tags
C#

© 2016 - 2018 - IntermittentBug