Threads run in a shared memory space
Processes run in separate memory spaces. each process has its own memory space and at least 1 thread, know as primary thread.
Thread
- Able observe its state. (specify name for debugging, Show in UI)
- Able to set thread-level properties (stack size, apartment state, or culture)
- Maintain an object owned by a single thread. ( Only used by that thread)
- Problem : costly, Each thread consumes a non-trivial amount of memory for its stack
ThreadPool
- Is a wrapper around a pool of threads, no create its own OS thread.
- Use for Short Operations & no result return.
- Use to avoid overhead of creating too many threads.
- Able to execute at some point.
- Able control the size of the pool,
- Not able to tell the pool start running the work.
- It will full , if too many long-running tasks.
- Not able to get the result (which item has been completed.)
Task
- Is lightweight object for managing a parallelizable unit of work. (work something in Parallel).Parallel means the work is spread across multiple processors to maximize computational speed.
- Does not create its own OS thread.(Executed by a TaskScheduler, run on threadPool)
- Unlike the ThreadPool, Task able to find out when it finishes, to return a result.
- Call ContinueWith() to run more code once the task finishes, and pass you the task's result.
- Call Wait() to synchronously wait for a task to finish. Like Thread.Join(), this will block the calling thread until the task finishes. Synchronously waiting for a task is bad idea; it prevents the calling thread from doing any other work, and lead to deadlocks if the task ends up waiting (even asynchronously) for the current thread.
- Parallel.For*() methods, PLINQ, C# 5 await, and modern async methods in the BCL, are all built on Task.
Conclusion
Task is almost always the best option; it provides a much more powerful API and avoids wasting OS threads.