Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ThreadPool.QueueUserWorkItem vs Task.Factory.StartNew

What is difference between the below

ThreadPool.QueueUserWorkItem 

vs

Task.Factory.StartNew 

If the above code is called 500 times for some long running task, does it mean all the thread pool threads will be taken up?

Or will TPL (2nd option) be smart enough to just take up threads less or equal to number of processors?

like image 483
stackoverflowuser Avatar asked Feb 08 '12 20:02

stackoverflowuser


People also ask

What is the difference between task run and task factory StartNew?

Run(action) internally uses the default TaskScheduler , which means it always offloads a task to the thread pool. StartNew(action) , on the other hand, uses the scheduler of the current thread which may not use thread pool at all!

When should you not use ThreadPool?

Thread pools do not make sense when you need thread which perform entirely dissimilar and unrelated actions, which cannot be considered "jobs"; e.g., One thread for GUI event handling, another for backend processing. Thread pools also don't make sense when processing forms a pipeline.

What is ThreadPool QueueUserWorkItem?

QueueUserWorkItem(WaitCallback, Object) Queues a method for execution, and specifies an object containing data to be used by the method. The method executes when a thread pool thread becomes available.

Does Task use ThreadPool?

By default, TPL types like Task and Task<TResult> use thread pool threads to run tasks. You can also use the thread pool by calling ThreadPool.


1 Answers

If you're going to start a long-running task with TPL, you should specify TaskCreationOptions.LongRunning, which will mean it doesn't schedule it on the thread-pool. (EDIT: As noted in comments, this is a scheduler-specific decision, and isn't a hard and fast guarantee, but I'd hope that any sensible production scheduler would avoid scheduling long-running tasks on a thread pool.)

You definitely shouldn't schedule a large number of long-running tasks on the thread pool yourself. I believe that these days the default size of the thread pool is pretty large (because it's often abused in this way) but fundamentally it shouldn't be used like this.

The point of the thread pool is to avoid short tasks taking a large hit from creating a new thread, compared with the time they're actually running. If the task will be running for a long time, the impact of creating a new thread will be relatively small anyway - and you don't want to end up potentially running out of thread pool threads. (It's less likely now, but I did experience it on earlier versions of .NET.)

Personally if I had the option, I'd definitely use TPL on the grounds that the Task API is pretty nice - but do remember to tell TPL that you expect the task to run for a long time.

EDIT: As noted in comments, see also the PFX team's blog post on choosing between the TPL and the thread pool:

In conclusion, I’ll reiterate what the CLR team’s ThreadPool developer has already stated:

Task is now the preferred way to queue work to the thread pool. 

EDIT: Also from comments, don't forget that TPL allows you to use custom schedulers, if you really want to...

like image 101
Jon Skeet Avatar answered Sep 21 '22 06:09

Jon Skeet