Threads are an operating system feature that lets application logic be separated into several concurrent execution paths. This feature is useful when complex applications have many tasks that can be performed at the same time.
When an operating system executes an instance of an application, it creates a unit called a process to manage the instance. The process has a thread of execution. This is the series of programming instructions performed by the application code. For example, if a simple application has a single set of instructions that can be performed serially, there is just one execution path or thread through the application. More complex applications may have several tasks that can be performed in tandem, instead of serially. The application can do this by starting separate processes for each task. However, starting a process is a resource-intensive operation. Instead, an application can start separate threads. These are relatively less resource-intensive. Additionally, each thread can be scheduled for execution independently from the other threads associated with a process.
Threads allow complex applications to make more effective use of a CPU, even on computers that have a single CPU. With one CPU, only one thread can execute at a time. If one thread executes a long-running operation that does not use the CPU, such as a disk read or write, another one of the threads can execute until the first operation is completed. By being able to execute threads while other threads are waiting for an operation to be completed, an application can maximize its use of the CPU. This is especially true for multi-user, disk I/O intensive applications such as a database server. Computers that have multiple microprocessors or CPUs can execute one thread per CPU at the same time. For example, if a computer has eight CPUs, it can execute eight threads at the same time.
The problem with Thread is that OS threads are costly. Each thread you have consumes a non-trivial amount of memory for its stack, and adds additional CPU overhead as the processor context-switch between threads. Instead, it is better to have a small pool of threads execute your code as work becomes available.
ThreadPool is a wrapper around a pool of threads maintained by the CLR. ThreadPool gives you no control at all; you can submit work to execute at some point, and you can control the size of the pool, but you can’t set anything else. You can’t even tell when the pool will start running the work you submit to it.
Using ThreadPool avoids the overhead of creating too many threads. However, if you submit too many long-running tasks to the threadpool, it can get full, and later work that you submit can end up waiting for the earlier long-running items to finish. In addition, the ThreadPool offers no way to find out when a work item has been completed (unlike Thread.Join()), nor a way to get the result. Therefore, ThreadPool is best used for short operations where the caller does not need the result.
A task is a lightweight object for managing a parallelizable unit of work. A task avoids the overhead of starting a dedicated thread by using the CLR’s thread pool: this is the same thread pool used by ThreadPool.QueueUserWorkItem, but in CLR 4.0 it is enhanced to work more efficiently with Tasks.
Tasks can be used whenever you want to execute something in parallel; in CLR 3.0 / 3.5 we would have used the ThreadPool for this. However, the advantage of tasks is that they are tuned for leveraging multicores, unlike the ThreadPool by itself. In fact, the Parallel class and PLINQ are internally built on the task parallelism constructs.
A question answerd by Eric Lippert in Stack Overflow :
Q: what is diffrence between a Task and a Thread?
A: Suppose you are running a book delivery company. You have four cars and four drivers. A car is a thread, a driver is a processor, and a book delivery is a task. The problem you face is how to efficiently schedule the drivers and cars so that the tasks get done as quickly as possible.
Where things get weird is when there are more cars (threads) than drivers (processors). What happens then is halfway through a trip the driver parks one car (suspends the thread) and gets into a different car (switches context), drives that one around for a while performing tasks, and then eventually comes back to the first car. Obviously that is not as efficient as one driver staying in one car.
The idea of task-based parallism is to break up the work into small tasks that can produce results in the future, and then efficiently allocate exactly as many threads as there are processors so that you don’t waste time context switching. In practice, it usually does not work out that nicely, but that’s the idea.
which one is better, task or thread?
The question cannot be answered because it doesn’t make any sense. Which is better, a book to deliver to a customer, or a car to deliver it in? A car is a device that can be used to deliver a book; those two things are not things you can sensibly describe as “better” or “worse” than the other. It’s like asking “which is better, a hole or a drill?”
The bottom line is that Task is almost always the best option; it provides a much more powerful API and avoids wasting OS threads.
The only reasons to explicitly create your own Threads in modern code are setting per-thread options, or maintaining a persistent thread that needs to maintain its own identity.