Threading – using the ThreadPool vs. creating your own threads

Yan Cui

I help clients go faster for less using serverless technologies.

This article is brought to you by

Don’t reinvent the patterns. Catalyst gives you consistent APIs for messaging, data, and workflow with key microservice patterns like circuit-breakers and retries for free.

Try the Catalyst beta

There are a lot of discussions on the pros and cons of using the ThreadPool and creating your own threads. Having spent a bit of time reading what others have to say, here’s a summary of the things I’ve picked up on.

The problem with creating your own threads

Creating and destroying threads has a high CPU usage, so when you need to perform lots of small, simple tasks concurrently the overhead of creating your own threads can take up a significant portion of the CPU cycles and severely affect the final response time. This is especially true in stress conditions where executing multiple threads can push CPU to 100% and most of the time would be wasted in context switching (swapping threads in and out of the processor along with their memory).

Using the Thread Pool

This is where the .Net Thread Pool comes in, where a number of threads are created ahead of time and kept around to pick up any work items you give them to do, without the overhead associated with creating your own threads.

When not to use the Thread Pool

In an ideal world you would always want to use the Thread Pool, but there are some real-world limitations. Most importantly, and the reason why most experts would tell you not to use the Thread Pool except for brief jobs is that: there is a limited number of threads in the .Net Thread Pool (250 per CPU by default), and they are being used by many of the .Net framework classes (e.g. timer events are fired on thread pool threads) so you wouldn’t want your application to hog the thread pool.

There are also a number of situations where you shouldn’t use the thread pool:

  • You require a foreground thread, all the thread pool threads are background threads
  • You require a thread to have a particular priority.
  • You have tasks that cause the thread to block for long periods of time. The thread pool has a maximum number of threads, so a large number of blocked thread pool threads might prevent tasks from starting.
  • You need to place threads into a single-threaded apartment. All ThreadPool threads are in the multithreaded apartment.
  • You need to have a stable identity associated with the thread, or to dedicate a thread to a task.

Exceptions in Thread Pool threads

Unhandled exceptions on thread pool threads terminate the process with 3 exceptions:

  • A ThreadAbortException is thrown in a thread pool thread, because Abort was called.
  • An AppDomainUnloadedException is thrown in a thread pool thread, because the application domain is being unloaded.
  • The common language runtime (CLR) or a host process terminates the thread.

When to create your own threads

As I’ve mentioned already, creating your own threads is bad when lots of simple tasks require a relative large overhead in context switching, and the Thread Pool is bad for long running, or blocking tasks. Which leads to the natural conclusion :-P – create your own threads for long running, or blocking tasks!

Parting thoughts…

When working with the Thread Pool there are some useful methods at your disposable, including:

  • GetAvailableThreads method which returns the number of threads available to you
  • GetMinThreads method returns the number of idle threads the thread pool maintains in anticipation of new requests
  • GetMaxThreads method returns the max number of thread pool threads that can be active concurrently
  • SetMinThreads method sets the number of idle threads the thread pool maintains in anticipation of new requests
  • SetMaxThreads method sets the number of thread pool threads that can be active concurrently

If you’re interested in how the ThreadPool class dynamically manages the size of the thread pool under the hood (despite giving you the option to set min and max threads) you should have a read of Pedram Razai’s blog post in the reference section.

And before you go, I mentioned earlier that all Thread Pool threads are background threads, so how do they differ from foreground threads? Well, foreground and Background threads are identical with one exception: a background thread does not keep the managed execution environment running. Once all foreground threads have been stopped in a managed process (where the .exe file is a managed assembly), the system stops all background threads and shuts down.

References:

StackOverflow question on Thread Pool vs Thread Spawning

Another StackOverflow question on Thread Pool vs Thread Spawning

StackOverflow question on when to use the Thread Pool in C#

StackOverflow question on managing the size of the Thread Pool in C#

StackOverflow question with detail on the throttling behaviour of the ThreadPool

MSDN article on The Managed Thread Pool

MSDN C# Programming Guide : how to use a ThreadPool

MSDN article on why we need a thread pool

Jon Skeet’s introductory article on Multi-threading in C#

Pedram Rezaei’s blog post on dedicated threads vs threadpool threads

Smart Thread Pool project on CodePlex

Whenever you’re ready, here are 3 ways I can help you:

  1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
  2. I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
  3. Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.

8 thoughts on “Threading – using the ThreadPool vs. creating your own threads”

  1. Pingback: Threading — introducing SmartThreadPool | theburningmonk.com

  2. Pingback: .Net Tips — Using custom ServiceThrottlingAttribute to specify WCF service throttling behaviour | theburningmonk.com

  3. Hey guys,

    My name is Daniel and I am from Stirling in the United Kingdom. I have not long ago discovered this forum and I like it alot.
    I am a bit shy so I wont write much about myself but maybe when I will get more confortable, you guys will get to know me better!
    My main hobbies are playing piano and watching movies. I also like outdoor activites but the temperature has been terrible for the last days or so here in Stirling in the city|.

    I was wondering if anyone else here is from the united Kingdom too?

    I am glad to have joined this forum!
    Cheers!
    :)

    Daniel

    PS: I apologize if this was posted in the wrong topic. I could not find the right one!

  4. Pingback: .Net Threading — BeginInvoke uses the thread pool | theburningmonk.com

  5. Pingback: C#: BeginInvoke « Tutorien

  6. Pingback: SmartThreadPool – What happens when you take on more than you can chew | theburningmonk.com

  7. Pingback: What number of threads to be created in thread pool – Best Java Answer

Leave a Comment

Your email address will not be published. Required fields are marked *