Site Loader
Auckland, New Zealand
In my last post we discussed on how to perform multiple execution of a method via Threads and using Task Parallel Library (TPL) for execution in Parallel. In this post we are going to discuss on even more improved way of executing methods via Async and Await but we are going to run them asynchronously

Async and await keywords are introduced in .Net 4.5 are the heart of Asynchronous programming and does all the magic.

 Let’s discuss with a simple example.

Consider we are going to perform a very complex I/O operation which reads an external file over network and renames the file and copies the renamed file in another folder of a different machine in network. Waiting for this operation to complete for just 1 file itself will take a long time (Depending upon network traffic, I/O speed and latency) and consider the same for thousands of file. While performing this resource intensive operation your UI will hang and your application will stop responding, since all UI related activity will always have Thread affinity (means they all run in same thread). To cope this problem we can use async and await keywords in combination.

Well, I am not going to discuss more about async and await in details, since the post is intended to demonstrate how to establish asynchronous execution using them.

In short, async will perform make a method to execute asynchronously, meaning it return to the caller immediately and await within async method will ensure the called async method is done with what it’s doing. I know it sounds very simple than what it is, you can read more about it from MSDN

 Let’s start writing the same code which we discussed in my previous post

Operation

I am trying to execute an SQL query (Insert query) 20 times and all I am planning to do is to test if the SQL server is fast enough to respond and inserts the record. All I am trying to achieve is maximum parallelism of operation (Inserting of record at same time). Here is the code which we discussed in our last post, which does parallel execution using Parallel.For

Code using Parallel.For

        public static void WithTPL(int ThreadCount)
        {
            //Create Parallel.For to execute the task
            Parallel.For(0, ThreadCount, i =>
            {
                ConnectDBAndExecuteQuery(i);
            });
        }
Code for ConnectDBAndExecuteQuery()
        public static void ConnectDBAndExecuteQuery(int ThreadNumber)
        {
            try
            {
                string sqlQuery = "insert into tblMasterLookup Values (" + ThreadNumber + ",'Test','2.0','Myapplication',GetDate()) waitfor delay '00:00:30'";
 
                string connectionString = @"Server=.\SQLEXPRESS;Database=AUTODATA;Password=abc123;User ID=sa";
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
                    using (SqlCommand command = new SqlCommand(sqlQuery, connection))
                    {
                        command.CommandTimeout = 80;
                        command.ExecuteNonQuery();
                        Console.WriteLine("Executed Thread.. " + Thread.CurrentThread.ManagedThreadId);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

Code using Async and Await

This time we are going to leverage the power of Async and Await, but here I am also going to use asynchronous ExecuteNonQuery method named ExecuteNonQueryAsync() Well this method is something shipped by Microsoft .Net and not by me J

Short history

Currently in Windows 8, all the resource intensive operations which ever takes more than 50 seconds are converted as asynchronous methods. You can see a list of asynchronous supported members from here   Back to code using async and await coding, as mentioned, I am going to use ExecuteNonQueryAsync, which means I need to make my method as Async and have to wait for ExecuteNonQueryAsync to complete its operation using await. Here is the modified code of ConnectDBAndExecuteQuery Code for ConnectDBAndExecuteQueryAsync
        public static async Task ConnectDBAndExecuteQueryAsync(int ThreadNumber)
        {
            try
            {
                string sqlQuery = "insert into tblMasterLookup Values (" + ThreadNumber + ",'Test','2.0','Myapplication',GetDate()) waitfor delay '00:00:30'";
 
                string connectionString = @"Server=.\SQLEXPRESS;Database=AUTODATA;Password=abc123;User ID=sa";
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    connection.Open();
                    using (SqlCommand command = new SqlCommand(sqlQuery, connection))
                    {
                        Console.WriteLine("Executed Thread.. " + Thread.CurrentThread.ManagedThreadId);
                        command.CommandTimeout = 80;
                        await command.ExecuteNonQueryAsync();
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }

As you can see now, I have given my method name as ConnectDBAndExecuteQueryAsync which is recommended by Microsoft coding convention. And here is the code to call the asynchronous method
        public static void UsingAsyncAwait(int ThreadCount)
        {
            for (int i = 0; i < ThreadCount; i++)
            {
                Task task = ConnectDBAndExecuteQueryAsync(i);
            }
        }

 

Performance Improvement with async and await

The whole reason for going async and await is for performance improvement by running resource intensive operations in parallel, well here is the improved performance and parallelism we achieved using async and await. With Parallel.For and Async/await, we could see lots and lots of improvement. It took just 140 milliseconds to perform same insert operation for async/await which took 18 seconds in Parallel.For.

Multithreading Async and Await

By default async and await are single threaded, which means while you execute the above code you can see the result clearly as shown below All the execution is happening with single thread. In order to make the async/await to run in multithread, we need to make use of Task.Run or Task.Factory.StartNew Here is the code
        public static void UsingAsyncAwaitWithTask(int ThreadCount)
        {
            Parallel.For(0, ThreadCount, i =>
            {
                Task.Factory.StartNew(() =>
                {
                    return ConnectDBAndExecuteQueryAsync(i);
                });
            });
        }

While executing the above code, the output looks something like this The thread number will change for each and every run and also for you and me.

Summary

In short, Async and Await in Asynchronous programming runs multiple operation same time, whereas Task Parallel Library (TPL) runs multiple operation by creating its own thread and run them in parallel. But the main difference is, Asynchronous returns to caller once it start operation and await will wait till the called method its done with what its doing, whereas parallel programming will create multiple threads and try run them all in parallel.

Post Author: Karthik kk

One Reply to “Using Async and Await for asynchronous operation also with multi-threading!!!”

  1. I’m trying like below but I’m getting connection closed error.

    using (SqlConnection connection = (SqlConnection)SqlHelper.OpenConnection())
    {
    Parallel.For(0, arr.Count(), i =>
    {
    Task.Factory.StartNew(() =>
    {
    return AzureToSqlAsync(arr[i], connection);
    });
    });
    }

    And :

    private async Task AzureToSqlAsync(string query, SqlConnection connection)
    {
    try
    {
    using (SqlCommand command = new SqlCommand(query, connection))
    {
    command.CommandTimeout = 80;
    await command.ExecuteNonQueryAsync();
    }

    }
    catch (Exception ex)
    {
    Console.WriteLine(ex.ToString());
    }
    }

Leave a Reply

Your email address will not be published. Required fields are marked *