110

I am just learning about the new Threading and Parallel libraries in .Net 4

In the past I would create a new Thread like so (as an example):

DataInThread = new Thread(new ThreadStart(ThreadProcedure));
DataInThread.IsBackground = true;
DataInThread.Start();

Now I can do:

Task t = Task.Factory.StartNew(() =>
{
   ThreadProcedure();
});

What is the difference if any?

Thanks

Jon
  • 38,814
  • 81
  • 233
  • 382
  • 1
    You'll need to fret a bit about how the thread pool scheduler works. It can make a big difference but that all depends on what you actually do inside the thread. – Hans Passant Oct 25 '11 at 13:18

4 Answers4

84

There is a big difference. Tasks are scheduled on the ThreadPool and could even be executed synchronous if appropiate.

If you have a long running background work you should specify this by using the correct Task Option.

You should prefer Task Parallel Library over explicit thread handling, as it is more optimized. Also you have more features like Continuation.

sanosdole
  • 2,469
  • 16
  • 18
  • 5
    No it doesn´t. It just starts tasks. This could enqueue the task at the thread pool or execute it synchronously. The TPL is about freeing you from managing the threads/concurrency yourself and using the best for your platform (like utilizing cores) – sanosdole Oct 25 '11 at 13:21
  • But the reason I create a thread is because I want to process code on another thread whilst the main thread is doing something else. Is there no way to specify that I want to do something always on another thread? – Jon Oct 26 '11 at 07:09
  • 11
    There is the TaskCreationOptions.LongRunning option that will always create another thread, but the whole point is why do you need another thread? If you just want to do something in parallel (Main does sth. while Task runs) it is preferable to let a optimized library decide how to utilize system resources like threads to do this in the most efficient way. – sanosdole Oct 26 '11 at 08:21
  • 3
    This msdn article describes how tasks are scheduled. It covers longrunning & inlining (synchronous execution). http://msdn.microsoft.com/en-us/library/dd997402.aspx – sanosdole Oct 26 '11 at 10:42
  • I need a new thread to process information sent to me on a socket so I'm trying to find the best way to do it – Jon Oct 27 '11 at 07:11
  • Also that thread needs to exist while the application is running eg/while (!ProgramEnding). Is there a knock on effect from using LongRunning as it doesnt use the ThreadPool – Jon Oct 27 '11 at 07:21
  • I do not know what you mean by a knock on effect. There has been a discussion on stack overflow whether the long running option guarantees a seperate thread. The current implementation seems to do just that. – sanosdole Oct 27 '11 at 19:14
  • @sanosdole you wrote: "but the whole point is why do you need another thread?" - what about the scenario where the main thread is servicing a UI request in a controller. In this case, you _definitely_ want a separate thread for some heavy-lifting, otherwise the UI will block. Or am I missing something? – sming May 06 '14 at 15:58
  • 2
    @sming The point is that you want to process concurrently (not blocking UI) not that you want a new thread. The ThreadPool will not block the UI thread, but manage the background threads much more efficient than you could do manually by creating threads. That is the change in the mind process that the TPL introduces. Don´t think threads, think concurrent tasks. – sanosdole May 07 '14 at 09:36
  • @sanosdole but you wrote "Tasks are scheduled on the ThreadPool and could even be executed synchronous if appropiate" which to me implies that the ThreadPool _may_ execute the task in the same thread, which would certainly block the UI. No? – sming May 07 '14 at 17:20
  • 4
    @sming Sorry, that sentence was a little bit too coarse. Synchronous execution of tasks is called inlining. When scheduling a task on the threadpool (default scheduler) from the UI Thread it will not occur. It will only occur if the ambient scheduler ('TaskScheduler.Current') is the same as the scheduler of a task you call '.Wait()' on. As '.Wait()' is blocking, it will be blocking the UI anyway. Short: Don´t call wait and it will not be executed synchronously. – sanosdole May 08 '14 at 11:31
76

The task gives you all the goodness of the task API:

  • Adding continuations (Task.ContinueWith)
  • Waiting for multiple tasks to complete (either all or any)
  • Capturing errors in the task and interrogating them later
  • Capturing cancellation (and allowing you to specify cancellation to start with)
  • Potentially having a return value
  • Using await in C# 5
  • Better control over scheduling (if it's going to be long-running, say so when you create the task so the task scheduler can take that into account)

Note that in both cases you can make your code slightly simpler with method group conversions:

DataInThread = new Thread(ThreadProcedure);
// Or...
Task t = Task.Factory.StartNew(ThreadProcedure);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 8
    +1. I'd like to add that `Thread` is very low-level compared to `Task` (I have a [blog post](http://nitoprograms.blogspot.com/2010/08/various-implementations-of-asynchronous.html) that goes into detail). I'm giving a "using Tasks in the real world" kind of talk at [Grand Rapids DevDay](http://grdevday.org/). The talk is called "Thread is Dead", because there's no longer any need for `Thread` (unless you're implementing a `TaskScheduler`). – Stephen Cleary Oct 25 '11 at 13:26
  • @StephenCleary, I assume that you mean `Thread` is dead, when it comes to being used as a background thread? – ebb Oct 25 '11 at 21:11
  • 1
    @ebb: No, I take the stronger position described in my first comment. There's nothing `Thread` can do (or `BackgroundWorker`) that can't be done more elegantly with `Task` and an appropriate `TaskScheduler`. – Stephen Cleary Oct 25 '11 at 21:42
  • 1
    @StephenCleary, How would you create a dedicated thread, without using `Thread`? – ebb Oct 25 '11 at 21:59
  • 5
    @ebb: "Dedicated thread" isn't clear to me. If you want a `Task` to run on a specific thread, then use an appropriate `TaskScheduler` - e.g., [`AsyncContextThread`](http://nitoasyncex.codeplex.com/wikipage?title=AsyncContextThread). However, this is usually not necessary; the `SynchronizationContext`, `ThreadPool`, and `ConcurrentExclusiveSchedulerPair` schedulers are sufficient for most programs. – Stephen Cleary Oct 25 '11 at 22:33
  • But the Task is not guaranteed to run on another thread. How do you specify that you definately want it on another thread? – Jon Oct 26 '11 at 07:13
  • @JonSkeet : Can you give a link that briefs about the above mentioned mentioned, best in your knowledge. – wuhcwdc Jun 15 '13 at 15:23
  • @PankajGarg: If you mean the methods - just look on MSDN for the documentation. If you mean something else, you need to be more specific. – Jon Skeet Jun 15 '13 at 18:58
  • Here's the current link to Stephen Cleary's blog mentioned in his first comment: http://blog.stephencleary.com/2010/08/various-implementations-of-asynchronous.html – Sudhanshu Mishra Nov 11 '15 at 04:48
13

In the first case you are simply starting a new thread while in the second case you are entering in the thread pool.

The thread pool job is to share and recycle threads. It allows to avoid losing a few millisecond every time we need to create a new thread.

There are a several ways to enter the thread pool:

  • with the TPL (Task Parallel Library) like you did
  • by calling ThreadPool.QueueUserWorkItem
  • by calling BeginInvoke on a delegate
  • when you use a BackgroundWorker
alexandrekow
  • 1,927
  • 2
  • 22
  • 40
1

Your first block of code tells CLR to create a Thread (say. T) for you which is can be run as background (use thread pool threads when scheduling T ). In concise, you explicitly ask CLR to create a thread for you to do something and call Start() method on thread to start.

Your second block of code does the same but delegate (implicitly handover) the responsibility of creating thread (background- which again run in thread pool) and the starting thread through StartNew method in the Task Factory implementation.

This is a quick difference between given code blocks. Having said that, there are few detailed difference which you can google or see other answers from my fellow contributors.

s_nair
  • 812
  • 4
  • 12