Dot Net For All

How to perform C# Asynchronous operations

In this article I will discuss about the different ways in which we can perform a long running operation asynchronously in C#. I will discuss all the cases with examples. This will help you to decide which method you can opt for while working asynchronous programming.

Different ways to Perform C# asynchronous operations

    1. By using Delegates- The first way to perform a long running operation is by using the BeginInvoke() method of delegates. If you want to learn more about delegates you can learn in this article. By using begin invoke method of the delegate the CLR uses thread pool thread to perform the operation. I have used the Func delegate. You can read about the delegate type here.
              static Func<string, int> func;
              static void Main(string[] args)
              {
                  func = new Func<string, int>(PerformLongRunningOperation);
                  IAsyncResult ar = func.BeginInvoke("40", CallBack, null);
                  Console.Read();
              }
      
              private static void CallBack(IAsyncResult ar)
              {
                  int test = func.EndInvoke(ar);
                  Console.WriteLine(test);
              }
      
              private static int PerformLongRunningOperation(string arg)
              {
                  Thread.Sleep(2000);
                  return Convert.ToInt32(arg);
              }

      In the above code I have method named PerformLongRunningOperation() which takes long time to return the result. I have simulated it by sleeping the thread. Once the operation is complete I am fetching and displaying the result in Call back method.

    2. Creating a Thread – We can perform a long running operation by creating a dedicated thread for the particular operation. Read more about threading concepts in this article.
              static void Main(string[] args)
              {
                  ThreadStart ts = new ThreadStart(MyLongRunningOperation);
                  Thread th = new Thread(ts);
                  //Other way to call
                  // Thread th = new Thread(() => MyLongRunningOperation());
                  th.Start();
                  Console.Read();             
              }
      
              private static void MyLongRunningOperation()
              {
                  Console.WriteLine("Start The operation");
                  Thread.Sleep(5000);
                  Console.WriteLine("Operation Completed..");
              }

      Whenever we create a Thread, it is not created as background thread. It means the application will be alive if this is only thread we have in the application and it is running. But if we create this thread as the background thread the application will exit as soon as the control goes to the MyLongRunningOperation().

    3. Creating a parameterized thread – In the previous point I have created a thread which calls a parameterless method. But if we have to call a method with some parameter we should use ParameterizedThreadStart delegate. This delegate expects an object parameter. Please check the code below.
       static void Main(string[] args)
              {
                  ParameterizedThreadStart ts = new ParameterizedThreadStart(MyLongRunningOperation);
                  Thread th = new Thread(ts);
                  //Other way to call
                  // Thread th = new Thread(x => MyLongRunningOperation(x));
                  th.Start(5000);
                  Console.Read();          
              }
      
              private static void MyLongRunningOperation(object milisecsToWait)
              {
                  Console.WriteLine("Start The operation");
                  Thread.Sleep(Convert.ToInt32(milisecsToWait));
                  Console.WriteLine("Operation Completed..");
              }
    4. Creating a thread pool thread – We can call a long running method by creating a thread in thread pool. These threads are background threads. Please check the code below for reference. You can read more about thread pools in one of my article.
              static void Main(string[] args)
              {
                  ThreadPool.QueueUserWorkItem(MyLongRunningOperation);       
              }
      
              private static void MyLongRunningOperation(object milisecsToWait)
              {
                  Console.WriteLine("Start The operation");
                  Thread.Sleep(Convert.ToInt32(milisecsToWait));
                  Console.WriteLine("Operation Completed..");
              }
    5. Creating a task – The problem with creating dedicated threads and Thread pool thread is that  we cannot return values from the methods, the exception handling is difficult to get and there is no easier mechanism to cancel the operation. To negate all these problems Tasks have been introduced. TPL (Task parallel library ) uses the thread pool threads. To know more about the difference between thread and task please read this article.
              static void Main(string[] args)
              {
                  var task = Task.Factory.StartNew<int>(MyLongRunningOperations, "4000");
                  Console.WriteLine(string.Format("Task completed after {0} milliseconds", task.Result));
              }
      
              private static int MyLongRunningOperations(object input)
              {
                  Console.Write("Statrted The operation");
                  Thread.Sleep(Convert.ToInt32(input));
                  return Convert.ToInt32(input);
              }

      There is a very nice post written by Andras here at this link to start task in different ways.

    6. Using Async and Await- The next way by which we can start a asynchronous operations is by using async and await keywords. These keywords have been introduced in .NET 4.5. A simple example of the async await keyword is as following. Read more about async and await keyword in my article.
              static void Main(string[] args)
              {
                  var result = MyLongRunningOperations("4000");
                  Console.WriteLine(string.Format("Task completed after {0} milliseconds", result.Result));        
              }
      
              private static async Task<int> MyLongRunningOperations(object input)
              {
                  var task = await Task.Factory.StartNew<int>(Operation, "4000");            
                  Console.WriteLine("Task is retuned");
                  return task;
              }
      
              private static int Operation(object input)
              {
                  Console.WriteLine("Started The operation");
                  Thread.Sleep(Convert.ToInt32(input));
                  return Convert.ToInt32(input);
              }
    7. Using Background worker thread – The last method by which we can start a asynchronous operation is by using the BackgroundWorker class. Though, the usage of this class is reduced after introduction of the TPL and asunc await keywords in C#. But it is always better to know about one more feature. The example is mentioned below.
       static BackgroundWorker _worker;
              static void Main(string[] args)
              {
                  _worker = new BackgroundWorker();
                  _worker.DoWork += _worker_DoWork;
                  _worker.RunWorkerCompleted += _worker_RunWorkerCompleted;
                  _worker.RunWorkerAsync(4000);
                  Console.Read();
              }
      
              private static void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
              {
                  Console.WriteLine(e.Result);
              }
      
              private static void _worker_DoWork(object sender, DoWorkEventArgs e)
              {
                  Console.WriteLine("Started The operation");
                  Thread.Sleep(Convert.ToInt32(e.Argument));
                  e.Result = "Worker completed after " + e.Argument;
      
              }

Conclusion:

In this article I have discussed various ways by which we can start an asynchronous operations in C#. You can use any one of these operations based on the need and requirement of your project.

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview