Dot Net For All

Difference Between C# Task and Thread With Code

In my previous articles I have discussed about the basics about threading and working with thread pool in C#. In the later article I have discussed why do we need thread pool and how we can use tasks to create a thread pool thread. In this article i will compare the Task and thread with code examples. In the one point of the article I will show how we can use CancellationTokenSource to cancel a task using code.

Task and Thread Differences in C#

  1. Task is more abstract then threads. It is always advised to use tasks instead of thread as it is created on the thread pool which has already system created threads to improve the performance.
  2. Task is generally created on the thread pool which are treated as background threads while thread is by default not background which can verified by the code present in two below figures.
    In the above code I have created and started a thread in a console application. In the delegate for the thread I made that thread to sleep(which we should not do in real applications) for 3 seconds which denote a time taking method. If we run the application we can see that the application closes only after 3 seconds.
    Now in the case of task for the code in above figure. The application will shut down as soon as it is started, as task is created on background threads for which the main thread will not wait to complete.
  3. Thread Does Not Return Results– Thread cannot be used to directly return result from the method. Though we can use shared field to get the result whereas with task we can always get the return values as shown in the below code.
            static void Main(string[] args)
            {  
                Task<int> task = new Task<int>(LongRunningTask);
                task.Start();
                Console.WriteLine(task.Result);
            }
            private static int LongRunningTask()
            {
                Thread.Sleep(3000);
                return 1;
            }

    In the above code I have created a task which returns an integer. In the function LongRunningTask I am waiting for the task to complete by keeping Thread.Sleep and returning the integer value.Now whatever integer value is returned I can get that value by using Result property. Important point to note here is that if we are waiting for the result the main application will not shut down as long as the result is returned.

  4. No Continuation in Thread- We cant tell a thread to start some other operation when it is done with it work. Though we can wait for the thread to complete by using Join() but that will block out main thread.On the other hand we can tell the task to continue with the other task by using the ContinueWith() method of the task instance as shown in the below code.
            static void Main(string[] args)
            {
                Task<int> task = new Task<int>(LongRunningTask);
                task.Start();
                Task<int> childTask = task.ContinueWith<int>(SquareOfNumber);
                Console.WriteLine("Sqaure of number is :"+ childTask.Result);
                Console.WriteLine("The number is :" + task.Result);
            }
            private static int LongRunningTask()
            {
                Thread.Sleep(3000);
                return 2;
            }
            private static int SquareOfNumber(Task<int> obj)
            {
                return obj.Result * obj.Result;
            }
  5. Cancellation – We cannot cancel a thread while it is in middle of the operation. But cancellation in tasks are supported with the help of CancellationTokeSource class as shown in the code below. Though there can be different topic itself for cancellation technique itself in asynchronous programming.
    static void Main(string[] args)
            {
                using (var cts = new CancellationTokenSource())
                {
                    Task task = new Task(() => { LongRunningTask(cts.Token); });
                    task.Start();
                    Console.WriteLine("Operation Performing...");
                    if(Console.ReadKey().Key == ConsoleKey.C)
                    {
                        Console.WriteLine("Cancelling..");
                        cts.Cancel();
                    }                
                    Console.Read();
                }
            }
            private static void LongRunningTask(CancellationToken token)
            {
                for (int i = 0; i < 10000000; i++)
                {
                    if(token.IsCancellationRequested)
                    {
                        break;
                    }
                    else
                    {                  
                        Console.WriteLine(i);
                    }               
                }          
            }

    In the above code I am writing some numbers on the console which I can visualize as some long running task but while running this task I can cancel it, in this case by pressing “C” key which results in cancelling of the task.

  6. Exception – One of the major difference between task and thread is the propagation of exception. While using thread if we get the exception in the long running method it is not possible to catch the exception in the parent function but the same can be easily caught if we are using tasks.

Conclusion

I hope I have tried to best explain the difference between task and thread using code example. Please let me know your thought about the article. Going further you can check this article where I have demonstrated the practical usage of task in C# with code examples for continuation and exception handling.

References:

  1. Introduction To Async And Parallel Programming in .NET
  2. TPL Async

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview