Task vs Thread differences
Solution 1
Thread
is a lower-level concept: if you're directly starting a thread, you know it will be a separate thread, rather than executing on the thread pool etc.
Task
is more than just an abstraction of "where to run some code" though - it's really just "the promise of a result in the future". So as some different examples:
-
Task.Delay
doesn't need any actual CPU time; it's just like setting a timer to go off in the future - A task returned by
WebClient.DownloadStringTaskAsync
won't take much CPU time locally; it's representing a result which is likely to spend most of its time in network latency or remote work (at the web server) - A task returned by
Task.Run()
really is saying "I want you to execute this code separately"; the exact thread on which that code executes depends on a number of factors.
Note that the Task<T>
abstraction is pivotal to the async support in C# 5.
In general, I'd recommend that you use the higher level abstraction wherever you can: in modern C# code you should rarely need to explicitly start your own thread.
Solution 2
Usually you hear Task is a higher level concept than thread... and that's what this phrase means:
You can't use Abort/ThreadAbortedException, you should support cancel event in your "business code" periodically testing
token.IsCancellationRequested
flag (also avoid long or timeoutless connections e.g. to db, otherwise you will never get a chance to test this flag). By the similar reasonThread.Sleep(delay)
call should be replaced withTask.Delay(delay, token)
call (passing token inside to have possibility to interrupt delay).There are no thread's
Suspend
andResume
methods functionality with tasks. Instance of task can't be reused either.-
But you get two new tools:
a) continuations
// continuation with ContinueWhenAll - execute the delegate, when ALL // tasks[] had been finished; other option is ContinueWhenAny Task.Factory.ContinueWhenAll( tasks, () => { int answer = tasks[0].Result + tasks[1].Result; Console.WriteLine("The answer is {0}", answer); } );
b) nested/child tasks
//StartNew - starts task immediately, parent ends whith child var parent = Task.Factory.StartNew (() => { var child = Task.Factory.StartNew(() => { //... }); }, TaskCreationOptions.AttachedToParent );
So system thread is completely hidden from task, but still task's code is executed in the concrete system thread. System threads are resources for tasks and ofcourse there is still thread pool under the hood of task's parallel execution. There can be different strategies how thread get new tasks to execute. Another shared resource TaskScheduler cares about it. Some problems that TaskScheduler solves 1) prefer to execute task and its conitnuation in the same thread minimizing switching cost - aka inline execution) 2) prefer execute tasks in an order they were started - aka PreferFairness 3) more effective distribution of tasks between inactive threads depending on "prior knowledge of tasks activity" - aka Work Stealing. Important: in general "async" is not same as "parallel". Playing with TaskScheduler options you can setup async tasks be executed in one thread synchronously. To express parallel code execution higher abstractions (than Tasks) could be used:
Parallel.ForEach
,PLINQ
,Dataflow
.Tasks are integrated with C# async/await features aka Promise Model, e.g there
requestButton.Clicked += async (o, e) => ProcessResponce(await client.RequestAsync(e.ResourceName));
the execution ofclient.RequestAsync
will not block UI thread. Important: under the hoodClicked
delegate call is absolutely regular (all threading is done by compiler).
That is enough to make a choice. If you need to support Cancel functionality of calling legacy API that tends to hang (e.g. timeoutless connection) and for this case supports Thread.Abort(), or if you are creating multithread background calculations and want to optimize switching between threads using Suspend/Resume, that means to manage parallel execution manually - stay with Thread. Otherwise go to Tasks because of they will give you easy manipulate on groups of them, are integrated into the language and make developers more productive - Task Parallel Library (TPL) .
Solution 3
The Thread
class is used for creating and manipulating a thread in Windows.
A Task
represents some asynchronous operation and is part of the Task Parallel Library, a set of APIs for running tasks asynchronously and in parallel.
In the days of old (i.e. before TPL) it used to be that using the Thread
class was one of the standard ways to run code in the background or in parallel (a better alternative was often to use a ThreadPool
), however this was cumbersome and had several disadvantages, not least of which was the performance overhead of creating a whole new thread to perform a task in the background.
Nowadays using tasks and the TPL is a far better solution 90% of the time as it provides abstractions which allows far more efficient use of system resources. I imagine there are a few scenarios where you want explicit control over the thread on which you are running your code, however generally speaking if you want to run something asynchronously your first port of call should be the TPL.
Comments
-
Jacek almost 2 years
I'm new to parallel programming. There are two classes available in .NET:
Task
andThread
.So, my questions are:
- What is the difference between those classes?
- When is it better to use
Thread
overTask
(and vice-versa)?
-
MoonKnight over 11 yearsRead this.
-
Abhijit-K over 11 yearsPrefer Task unless you need thread. Thread need resources(1MB stack(in .net commited), thread kernel object, etc). Task's are also run parallely as separate thread but it is a system thread pool threads that are optimized by the system considering cpu cores, etc and is used to run many tasks across system. Other than this the task when completed can return an object, so there is convinient way to know what the result of parallel execution is.
-
Panzercrisis over 7 years@AbhijitKadam When you say "system", are you referring to the .NET framework?
-
Tsahi Asher almost 6 yearsWhile this is an interesting read, @MoonKnight, reading a book about threading is a bit of an overkill for a SO question.
-
MoonKnight almost 6 years@TsahiAsher it is a single chapter from a book.
-
Alex from Jitbit over 2 yearsI can't believe the most upvoted answer has been deleted (I can see it b/c of my big reputation). And there's no way to let mods know they made a mistake
-
Ignacio Soler Garcia over 10 yearsEven if you are running a message loop-like process you would use a task instead of a thread?
-
Jon Skeet over 10 years@SoMoS: Probably - you can create it as "long-running" and it will end up with a dedicated thread, but it means using a single abstraction throughout.
-
Royi Namir almost 10 years@JonSkeet Also , it's worth to mention that in asp.net -
new Thread()
is not dealing with Threadpool thread , whereasTask
does use threadpool thread — i.stack.imgur.com/O8AnU.jpg -
Jon Skeet almost 10 years@RoyiNamir: That's not really an ASP.NET-specific thing - and in some cases when you start a task it might use a non-thread-pool thread, if you specify that it's going to be a long-running task.
-
Luaan about 9 yearsNote -
Thread.Abort
doesn't work for most long operations like DB connections either. It can only abort while in managed code, while most of the long-waiting stuff is stuck in native code (e.g. waiting for a handle, I/O operations...). The only benefit is that it can abort anywhere in managed code, relatively safely (e.g. not infinally
clauses etc.), so it will help against errors like infinite loops etc. Using it in production-level code doesn't make much sense, though. -
Joren almost 9 years
Thread.Abort
is evil and should be avoided wherever possible. Code running under the possibility of a thread abort is incredibly difficult to reason about correctly. It's not worth it, just check some kind of flag. (I'd suggest theCancellationToken
API, even if you're not using Tasks) -
Leonid Vasilev over 8 years@JonSkeet can you please point out a few examples when you actually need to start your own thread in modern C#?
-
Jon Skeet over 8 years@Leonid: Not offhand... It does avoid the task scheduler needing to get involved at all... But yes, these days I'd stick to Task.Run.
-
Ed S. over 6 years@LeonidVasilyev: Not directly Task related (this was before Tasks were introduced), but I did starve the thread pool once doing some image analysis work. I was using (too many really) the thread pool for object detection, but was pushing the results using an SDK which also used the threadpool. This caused my program to lock up because all threads were busy.
-
Rekshino over 5 yearsIt's an error to do so
Thread.Sleep(delay)
should be replaced withTask.Delay(delay, token);
If, then it should be replaced withTask.Delay(delay, token).Wait();
, which is the same asThread.Sleep(delay)
, or withawait Task.Delay(delay, token)
, if it is possible. -
zionpi about 5 yearsWhat if I want to use
Task
in realtime system,I need to pause and resume,cancel and stop,doesTask
works even in that harsh cirmustance? -
Jon Skeet about 5 years@zionpi: No,
Task
has no concept of pausing. -
Boppity Bop almost 5 yearsTask is a poor man thread. Running task in same thread as it was called from is not what a high throughput low latency server developer would use ever.