You are here

Usage of await and async in .NET

Async methods are intended to be non-blocking operations. An await expression in an async method doesn't block the current thread while the awaited task is running. Instead, the expression signs up the rest of the method as a continuation and returns control to the caller of the async method.

Here, we demonstrate two ways to use async method.
A. Calling a system API (for example using HttpClient get response)
B. Making my own functions that can behave as system provided API, in the following example ProcessMyOwnLongRunningMethodAsync() is developed as custom async method.

When we call await method then the call comes back to the caller. In our example to the main method. Main method will print the dot dot. See how we are modifying the mJobDone variable. If you add the while loop from main and put it before or after the await then see how it works.

using System;
using System.Net.Http;
using System.Threading;

namespace ThreadTest
{
    class TaskAsyncExample
    {
        private static bool mJobDone = false;
        public static void Main ( )
        {
            CallWaitingMethod ( );
            Console.WriteLine ( "Working " );
            while (mJobDone == false)
            {
                Console.Write ( "." );
                Thread.Sleep ( 200 );
            }
            Console.ReadKey ( );
        }

        private static async void CallWaitingMethod ( )
        {
            /*
             * 
             *  Comment the following code to call system async methods.
             *  This method shows how to create own async task
             * */
            Task<string> strTask = ProcessMyOwnLongRunningMethodAsync ( "Mahbub" );
            string asyncresult = await strTask;
            mJobDone = true;

            /*
             *  Un comment the following code to call some real long running system methods
             * */

            //string asyncresult;
            //using (HttpClient client = new HttpClient ( ))
            //{
            //    asyncresult = await client.GetStringAsync ( "http://microsoft.com" );
            //    mJobDone = true;
            //}

            Console.WriteLine ( "\n" + asyncresult );
            Console.WriteLine ( "Work Done" );
        }
        private static Task<string> ProcessMyOwnLongRunningMethodAsync ( string name )
        {            
            // return Task.Factory.StartNew<string> (() => ActualLongRunningOwnMethod(name));
            //Can be used also in the following way
            return Task.Run(new Func<string> (() => ActualLongRunningOwnMethod(name)));
        }

        private static string ActualLongRunningOwnMethod ( string name )
        {
            Thread.Sleep ( 3000 );
            return "Hello " + name;
        }
    }
}

Naming convention is used while using async and await keywords.
A. If a method return Task or Task then we use Async at the end of function name, for example
Task ProcessMyOwnLongRunningMethodAsync ( string name )
B. If a function use await keyword in front of a method then the method should declare it self with async. For example, private static async void CallWaitingMethod ( ). If async is not use then compiler will generates error.
Previous code return Task we modified the same example just to return only Task

namespace ThreadTest
{

    class TaskAsyncExample
    {
        private static bool mJobDone = false;
        public static void Main ( )
        {
            CallWaitingMethod ( );
            Console.WriteLine ( "Working " );
            while (mJobDone == false)
            {
                Console.Write ( "." );
                Thread.Sleep ( 200 );
            }
            Console.ReadKey ( );
        }

        private static async void CallWaitingMethod ( )
        {
            Task strTask = ProcessMyOwnLongRunningMethodAsync ( "Mahbub" );
            await strTask;
            mJobDone = true;
            Console.WriteLine ( "\nWork Done" );
        }
        private static Task ProcessMyOwnLongRunningMethodAsync ( string name )
        {
            Task t = Task.Factory.StartNew ( ( ) => { ActualLongRunningOwnMethod ( name); } );
            return t;
        }

        private static string ActualLongRunningOwnMethod ( string name )
        {
            Thread.Sleep ( 3000 );            
            return "Hello " + name;
        }
    }
}