Sunday 26 July 2015

Asynchronous Programming with Async and Await in C# 5.0

There are lot of articles available over the internet on this topic. few of them are nicely explained but some makes you confusing on these terms.

Actually I was going through this concept and realized why don't I blog it for you to make it simple in understanding. So let me try to explain Asynchronous Programming with Async and Await in a way I understand.

Async and Await:
           These are two keywords of C# and It's introduced in C#5.0 as part of .NET Framework 4.5. These two keywords helps you to write asynchronous programming  code (which will see down here) without any delegate, event or threading complex logic. Actually C# does that complex job internally when you use Async and Await.
Looking into below given example, you will realize it is easy and equivalent as normal synchronous programming code. 

Before we proceed let me tell you few basic mandates about async and await:
  1. await can be used only inside async method (method defines with async keyword)
  2. async methods can use only void, Task or Task<T> as return type.
  3. A method can not awaited (we can't use await with method call), if method is not async and doesn't return a Task. 
  4. Always use 'Async' as suffix to your async methods. (this is not mandatory but a guideline which helps to differentiate async and normal methods) 



Let see the example.
Here I am going to create an async method which returns void. Only purpose of this method is to enable my method to use await inside this method.

public async void DoMyCalculation()
{
     int primeLimit = 10;
     Task<IEnumerable<int>> primeNumsTask = GetPrimeNumbersAsync(primeLimit);

     DoSomeTasksHere();

     IEnumerable<int> primeNums = await primeNumsTask;

     Console.WriteLine("Sum of all prime numbers from 1 to " + primeLimit + " is: " + primeNums.Sum());
}

This method will do lot of tasks/calculation including finding sum of prime numbers within a limit. Here my purpose is, I want to calculate sum of prime numbers asynchronously so that it will not stop/interrupt other tasks which might be written inside DoSomeTasksHere() like methods.

In above method,

Task<IEnumerable<int>> primeNumsTask = GetPrimeNumbersAsync(primeLimit);

Says, there is async method called ‘GetPrimeNumbersAsync’ which returns an IEnumerable list of prime numbers(int) within the range provided. But above code actually means, you will get the prime numbers only when you await the task using below line of code.

IEnumerable<int> primeNums = await primeNumsTask;

Here ‘GetPrimeNumbersAsync’ methods will initiate the execution and control will be returned to the calling method ‘DoMyCalculation()’ and control will move forward to execute ‘DoSomeTasksHere()’ method as per our code.
Now let see how we need to define our async method ‘GetPrimeNumbersAsync()’:

public async Task<IEnumerable<int>> GetPrimeNumbersAsync(int limit)
{
     Console.WriteLine("Start GetPrimeNumbersAsync() call");
         
     IEnumerable<int> primeNums = FindPrimeNumbers(limit);

     Console.WriteLine("End GetPrimeNumbersAsync() call");

     return primeNums;
}

private IEnumerable<int> FindPrimeNumbers(int limit)
{
      Console.Write("PrimeNumbers:");
      for (int i = 1; i <= limit; i++)
      {
           Thread.Sleep(1000);
           if (i % 2 == 0)
           {
               Console.Write(i + " ,");
               yield return i;
           }
      }
      Console.WriteLine();
}

So as per the concept, to define a method async we need to declare method with async keyword and return type should of Task<T> (In our case it is Task<IEnumerable<int>>.
That’s all. Here is the complete code:




namespace TestConsoleApp
{
    public class AsyncAwait
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Main() call starts.");
            AsyncAwait program = new AsyncAwait();
            program.DoMyCalculation();
           
            Console.WriteLine("Main() call ends.");

            Console.ReadLine();
        }

        public async void DoMyCalculation()
        {
            int primeLimit = 10;
            Task<IEnumerable<int>> primeNumsTask = GetPrimeNumbersAsync(primeLimit);

            DoSomeTasksHere();

            IEnumerable<int> primeNums = await primeNumsTask;
            Console.WriteLine("Sum of all prime numbers from 1 to " + primeLimit + " is: " + primeNums.Sum());
        }

        public async Task<IEnumerable<int>> GetPrimeNumbersAsync(int limit)
        {
            Console.WriteLine("Start GetPrimeNumbersAsync() call");
         
            IEnumerable<int> primeNums = FindPrimeNumbers(limit);

            Console.WriteLine("End GetPrimeNumbersAsync() call");

            return primeNums;
        }

        private IEnumerable<int> FindPrimeNumbers(int limit)
        {
            Console.Write("PrimeNumbers:");
            for (int i = 1; i <= limit; i++)
            {
                Thread.Sleep(1000);
                if (i % 2 == 0)
                {
                    Console.Write(i + " ,");
                    yield return i;
                }
            }
            Console.WriteLine();
        }

        private void DoSomeTasksHere()
        {
            Console.WriteLine("DoSomeTasksHere() call : I am Sleeping.");
            Thread.Sleep(10000);
            Console.WriteLine("DoSomeTasksHere() end : I woke up.");
        }
    }

}

Now if you run the above program, this is what you will get as output in output window.

Main() call starts.
Start GetPrimeNumbersAsync() call
End GetPrimeNumbersAsync() call
DoSomeTasksHere() call : I am Sleeping.
DoSomeTasksHere() end : I woke up.
PrimeNumbers:2 ,4 ,6 ,8 ,10 ,
Sum of all prime numbers from 1 to 10 is: 30
Main() call ends.







Done.
Thank you for reading.
Feel free to provide your feedback/comments.

Reference: https://msdn.microsoft.com/en-us/library/hh191443.aspx



No comments:

Post a Comment