How to perform C# Asynchronous operations

By | January 6, 2017

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.

      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.

      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.
    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.
    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.

      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.
    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.


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.

  • Dmitry Bytchenko

    Many of the methods described (“Using Delegates”, “Creating a Thread”, “Using Background worker thread”…) are obsolete ones; so, please, let them rest in peace. Using these approaches nowadays is like assembling Boeing-747 in a garage. Task (esp. with async + await) is the trend.

  • Dmitry Bytchenko

    Task.Factory.StartNew is an evil: you don’t know in which context the Task will be created (it will be created in the caller’s context by default; and what is the caller context then? Caller is the method I am – not you – developing, so how can you be sure that my weird context will be OK in your case)). Another issue is with async delegates: you’ll get Task<Task> wait/await the wrong (outer) Task and have to keep in mind to add Unwrap(). That’s why Task.Run() is a better choice.