Async 1 - Getting Started With Asynchronous programming

Asynchronous execution explained with examples.

Wed, 06 Feb 2019

Intro

This post is part of 4 post blog series. In this series i will start with an introduction about the asynchronous programming and then we will explore more details about the asynchronous programming and it benefits then finally we will go through how we can start using asynchronous programming in our applications. This is the First Post in the series

Below is the list of all the posts from the series

  1. What is Asynchronous execution Real life and C# example(This Post)
  2. Why you should you consider it as a web developer?
  3. How async/await works Details of StateMachine working
  4. Demo: Refactoring an application to be asynchronous

What is Asynchronous execution Real life and C# example?

Text book definition of asynchronous programming:

Asynchronous, in computer programming, refers to the occurrence of events independent of the main program flow and ways to deal with such events. These may be “outside” events such as the arrival of signals, or actions instigated by a program that take place concurrently with program execution, without the program blocking to wait for results

If that confused you and did not made much sense don’t worry i was in the same boat as you when i first read it.

I think a real world example will clear up things a little. We do things asynchronously in our everyday life and it feels natural to do things in that asynchronous fashion.

Real life example

Trust me we do things in asynchronous fashion in everyday life without even realizing but it is the natural thing to do and does not feel like we are doing anything special at all.

Scenario:

Ranj(One of our actors) is walking to his office in the morning and saw a nice new cafe and decides to grab a cup of coffee.

Actors:

  1. Ranj: the person who wants to buy coffee
  2. Attendant: Person at the cafe counter
  3. Barista: Who makes the coffee
  4. Pastry Chef: The guy who serves snacks and bakery stuff.

Scenario

  • Ranj : Walks to the counter. Can i have a medium cappuccino please? (Main Thread)

  • Attendant : Sure! and ask barista to make one cup of cappuccino

  • Ranj : Feels craving to eat something Can I also have a muffin please

  • Attendant : Sure, Asks pastry chef for a muffin. (Async call)

  • Attendant : Anything else

  • Ranj : No (main thread)

  • Attendant : 10 dollars please.

  • Ranj : Pay the money.(main thread)

  • Attendant : Start Serving Next customer

  • Ranj : Start checking your twitter timeline and do other stuff while waiting (main thread)

  • Pastry Chef : Here is your muffin (Second Async call returns)

  • Ranj : Thanks! Go back to phone to check twitter.

  • Barista : Here is your coffee (First Async Action returns)

  • Ranj : You take stuff and leave shop (main thread) (Call the finally block)

So this is an example of what a asynchronous flow of execution looks like

  • Ranj order coffee as you don’t have any effort in involved in making coffee
  • Ranj order the muffin while Barista is making coffee.
  • While Pastry chef deliver the muffin you paid for bill as Ranj again have no efforts involved in preparing muffin.
  • Then Ranj got the muffin from pastry chef and then Barista gives Ranj the coffee now Ranj have everything he ordered Ranj leaves the cafe.

In short while you are waiting for someone else to do stuff for you. Instead of just waiting there you can do other tasks or ask others to do more stuff for you. This can result in better utilization of resources at hand

In the computer world this Barista can be some database query that you are waiting to be executed and return results or an external Http request to an api that you are waiting for reply.

How synchronous flow will look like for above scenario ?

If now we live in real life like asynchronous programming Ranj will wait for barista to make coffee before Ranj order the muffin and then he wait for muffin then pay the money then the next person in the queue can be served. I am pretty sure the person next in queue will not be very happy about that. The whole scenario looks very inefficient but many rookie programmers like me do this everyday in their applications(These applications serving real world people).

Benefits

So benefit of doing stuff asynchronous helped Ranj to get his coffee and Muffin delivered faster (performance) and also helped attendant to server more customers (scalability). This is true in case of computer programs also it helps with performance and scalability of the code and can be used in almost every scenario.

If you can relate to the above scenario and want to reap benefits of doing things in asynchronous fashion and want to find out find how you can do it in your applications. Don’t worry i got your covered. You can start writing asynchronous applications using async/await.

C# code example

The example above must have made things bit clear what is asynchronous programming. It is something very obvious with a fancy name. In the past writing asynchronous was more challenging but C#5 Introduced async/await it was a game changer and asynchronous programming became lot more strightforward with C# and .NET ecosystem.

Let’s see an example using C# to demonstrate the synchronous and asynchronous flow of execution. I am pretty sure you have seen it around in one of the projects you worked. Even if you never seen it before thanks to async/await keywords anybody can start writing async code in matter of few minutes.

There are multiple Azure SDKs and .NET types with async method.

Lets use the example of very simple http request using the Http client.

using System;
using System.Diagnostics;
using System.Net.Http;
using System.Threading.Tasks;

namespace Scenario
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                //We block the calling thread until the OrderAsync Completes
                OrderAsync().GetAwaiter().GetResult();
                Console.WriteLine();
                Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++++");
                Console.WriteLine("Lets Try Synchronous Way Now");
                Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++++");
                Order();
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        

        #region Async Version

        static async Task OrderAsync()
        {
            Console.WriteLine("Scenario!");
            Console.WriteLine("Ranj: Ordered the coffee");
            var coffeeOrder = AsyncOrderCoffee();
            Console.WriteLine("Ranj: Ordered the Muffin");
            var muffinOrder = AsyncOrderMuffin();
            Console.WriteLine("Attendant: 10 Dollars Please");
            Console.WriteLine("Ranj: Pays the bill");
            Console.WriteLine("Ranj: Waiting for Order Checking Twitter");
            await Task.WhenAll(coffeeOrder, muffinOrder);
            Console.WriteLine("Ranj: Leaves the shop.");
        }

        static async Task<int> AsyncOrderCoffee()
        {
            Console.WriteLine("Attendant: Coffee Ordered Received");
            HttpClient client = new HttpClient();
            
            Console.WriteLine("Attendant: Ask barista for coffee");
            Task<string> getStringTask =
                client.GetStringAsync("https://msdn.microsoft.com");

            //Return the control to the calling method without holding up the execution thread
            string urlContents = await getStringTask;


            Console.WriteLine("Barista: Here is your cappuccino");
            return urlContents.Length;
        }

        static async Task<int> AsyncOrderMuffin()
        {
            Console.WriteLine("Attendant: Muffin Ordered Received");
            HttpClient client = new HttpClient();

            Task<string> getStringTask =
                client.GetStringAsync("https://msdn.microsoft.com");

            Console.WriteLine("Attendant: Ask Chef for Muffin");
            //Return the control to the calling method without holding up the execution thead
            string urlContents = await getStringTask;

            Console.WriteLine("Chef: Here is your muffin");
            return urlContents.Length;
        }


        #endregion


        #region Sync Version Now

        static void Order()
        {
            Console.WriteLine("Scenario!");
            Console.WriteLine("Ranj: Ordered the coffee");
            Console.WriteLine("Ranj: Cannot check twitter or move further while barista makes coffee because Synchronous call blocked the thread");
            var coffeeOrder = OrderCoffee();
            Console.WriteLine("Ranj: Ordered the Muffin");
            Console.WriteLine("Ranj: Cannot check twitter or move further while Chef Brings muffin because Synchronous call blocked the thread");
            var muffinOrder = OrderMuffin();
            Console.WriteLine("Attendant: 10 Dollars Please");
            Console.WriteLine("Ranj: Pays the bill");
            Console.WriteLine("Ranj: Leaves the shop.");
            
        }

        static int OrderCoffee()
        {
            Console.WriteLine("Attendant: Coffee Ordered Received");
            HttpClient client = new HttpClient();
            Console.WriteLine("Attendant: Ask barista for coffee");
            //Execution thread will not go any further until we have result of the Http Call
            var urlContents = client.GetStringAsync("https://msdn.microsoft.com").Result;
            Console.WriteLine("Barista: Here is your cappuccino");
            return urlContents.Length;
        }

        static int OrderMuffin()
        {
            Console.WriteLine("Attendant: Muffin Ordered Received");
            HttpClient client = new HttpClient();
            Console.WriteLine("Attendant: Ask Chef for Muffin");
            //Execution thread will not go any further until we have result of the Http Call
            var urlContents =
                client.GetStringAsync("https://msdn.microsoft.com").Result;

            Console.WriteLine("Chef: Here is your muffin");
            return urlContents.Length;
        }

        #endregion
    }



}

Here are the few things that we notices in the above code snippet.

  • You may have noticed the method declaration contains a keyword ‘async’ this keyword allows this method to be executed asynchronously.

  • The return type of method is Task<int> instead of Just int as this method is asynchronous in nature it will not return the int value but will return a Task that if successfully completes will result in an int value.

So in layman term Task<T> is like a promise to provide some result of type T in future if execution is successfull.

Here is what the execution flow looks like for both the synchronous and asynchronous variants of order method. This will clear up lot of things about how async/await changes the way our program executes.

Execution Result

Few Things to Notice about the asynchronous method execution:

  • After the console statement (“Ask Barista for coffee”) the control returned to calling method.
  • Method to order muffin was executed.
  • After the console statement (“Ask Chef for muffin”) control was the returned to the calling method.
  • Pay the Bill was executed in the code.
  • Then the thread was sitting idle then received the callback or wakeup from Order Muffin method
  • Then the callback or ‘callback’ from order coffee was received.
  • Then the asynchronously executed task were complete and code proceeded all the way to call the synchronous version of order.

Now if we make minor changes to the main method as below

static void Main(string[] args)
        {
            try
            {
                var awaiter = OrderAsync().GetAwaiter();
                Console.WriteLine();
                Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++++");
                Console.WriteLine("Lets Try Synchronous Way Now");
                Console.WriteLine("+++++++++++++++++++++++++++++++++++++++++++++++++");
                Order();
                 //We block the calling thread until the OrderAsync Completes
                awaiter.GetResult();
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

We will notice the output will change to :

Post Result Second Case

Things to Notice:

  • We started the execution of the Synchronous version of order method before the async version was complete.
  • This execution flow proves that the control was returned all the way back to Main method while waiting for async http calls to complete.
  • While the control was returned to the Main. The HttpCall call was still in progress and waiting for response.

What to expect in next post:

In the above code we had an example where we demonstrated how we can use the asynchronous programming using async/await to improve the throughput of the applications.

In next posts we will discuss why we need to adopt the asynchronous programming for our applications.

Loading...
Ranjeet Singh

Ranjeet Singh Software Developer (.NET, ReactJS, Redux, Azure) You can find me on twitter @NotRanjeet or on LinkedIn at LinkedIn