C# - What is the difference between threads and tasks?

I had a discussion a couple of weeks ago about tasks and threads. It occurred to me that I had rarely (never?) used threads and only ever used tasks. So I decided to write this post on threads and tasks. Let us jump right to it and define the two.


Defining threads and tasks

MSDN defines a Task as the following:

"a single operation that does not return a value and that usually executes asynchronously" (You can use Task<Result> to return a result).

Threads are not a .NET construct, they are built into your operating system. The thread class from .NET is just a way to create and manage threads. Wikipedia defines a thread as the following

"thread of execution is the smallest sequence of programmed instructions that can be managed independently by a scheduler"

So how are they different?

All in all a Task uses a thread in order to execute asynchronous. A Task can be seen as a convenient and easy way to execute something asynchronously and in parallel. In other programming languages and frameworks this may be known as a promise - "I promise will return to you at some point". A task will by default use the Threadpool, which saves resources as creating threads can be expensive. A threadpool is.. a pool of threads, which are ready to carry out instructions (if they are no occupied of course). You can see a Task as a higher level abstraction upon threads. Which could be a reason why they are under the System.Threading namespace.

You can accomplish the same with a thread as you can with a task. Take a look at the following examples, the first one is using a thread:

int result = 0;
Thread thread = new System.Threading.Thread(() => { 
    result = 1; 
});
thread.Start();
thread.Join();
Console.WriteLine(result); //is 1

The second example is using a task:

int result = await Task.Run(() => {
    return 1; 
});
Console.WriteLine(result); //is 1

In the above the use of Task is a lot simpler and has no thread jargon. You create a new task and wait synchroneously for the result using await. Normally a Task is all you need, I cannot remember if I have ever used a thread for something else than experimentation.

I hope you liked this post, let me know what you think in the comments!