Click here to Skip to main content
15,867,765 members
Articles / Programming Languages / C#

A Custom Thread Pool Implementation Using C#

Rate me:
Please Sign up or sign in to vote.
2.07/5 (11 votes)
10 Mar 2009CPOL2 min read 69.4K   886   17   17
This article describes a custom thread pool implementation using the .NET Framework and C# 3.0.

Introduction

The .NET Framework BCL contains a very nice implementation of a thread pool (the System.Threading.ThreadPool class).

But, this class is not suitable for the following scenarios:

  1. Long-running operations. Usually, for long-running operations, it is recommended to use the Thread class.
  2. ThreadPool is per process. It means that a situation when there is no available thread in the ThreadPool can happen pretty often. What if you have a very important and emergent work item and do not want to take such a risk? But pretty often, especially when you have an application with a number of app domains (like IIS or SQL server), you can run out of threads in the thread pool...
  3. ThreadPool does not support IAsyncResult. BeginInvoke methods of all delegates internally pass control to ThreadPool, but ThreadPool itself does not support IAsyncResult.

Generally, there are number of strict recommendations about when you should use ThreadPool and when you should use the Thread class directly or MulticastDelegate.BeginInvoke. The main problem of System.Threading.ThreadPool is that it is per process. So, if you have a set of very important tasks to do, and also have a set of third-party assemblies that you host in the application, there is always a probability that your important tasks will be delayed. In the case of the CustomThreadPool, you have a separate threadpool for each application domain.

You can have as many CustomThreadPools as application domains.

This is just the initial version of CustomThreadPool, and I plan to extend it in future. Maybe, instead of WaitHandles, I will use Monitor.Wait and Monitor.Pulse to achieve better flexibility (and probably performance).

Using the Code

The CustomThreadPool has three methods: QueueUserWorkItem, QueueUserWorkItemResult<tresult>, and RetreiveUserWorkItemResult.

A sample of how to use these methods is provided below:

C#
public static class Program
{
      //main entry point
      public static void Main()
      {
         //schedule of
         CustomThreadPool.QueueUserWorkItem(DoSomething);
         CustomThreadPool.QueueUserWorkItemResultt<int>(MyLongRunningFunc, 
                          MyLongRunningFuncFinished);
      }

      //my long-running task
      private static void DoSomething()
      {
          Console.WriteLine("Hello, world!");
      }

      //my long-running function
      private static int MyLongRunningFunc()
      {
          return 888;
      }

      //CustomThreadPool supports IAsyncResult
      private static void MyLongRunningFuncFinished(IAsyncResult result)
      {
         Console.WriteLine(CustomThreadPool.RetreiveUserWorkItemResult<int>(result)); 
      }
}

Points of Interest

I've learned a lot about multithreading, especially about volatile fields and IAsyncResult implementation.

History

  • 20 Nov, 2008 -- Initial Posting
  • 10 Mar, 2009 -- Added dispose functionality to CustomThreadPool. Class changed from static to "instanceable" to support creation of multiple instances within the same App Domain.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead bwin Interactive Entertainment AG
Austria Austria
The views expressed in my articles are mine and do not necessarily reflect the views of my employer.

if(youWantToContactMe)
{
SendMessage(string.Format("{0}@{1}.com", "liptchinski_vit", "yahoo"));
}

More info in my LinkedIn profile:
http://www.linkedin.com/in/vitaliyliptchinsky

Comments and Discussions

 
QuestionI found this very useful, with one little change. Pin
wookie2u@gmail.com2-Oct-12 21:16
wookie2u@gmail.com2-Oct-12 21:16 
GeneralDisposeImpl() is not working for big number of transactions Pin
Houssam Hamdan17-Jun-10 2:44
Houssam Hamdan17-Jun-10 2:44 
(pool as IDisposable).Dispose() method does not function properly sometimes for large number of transactions. The program still hangs without exit.

How many thread do you recommend to allocate at class initialization for 10,000 transactions per example?

Thank you in advance for your help.

Cheers,
GeneralRe: DisposeImpl() is not working for big number of transactions Pin
Vitaliy Liptchinsky17-Jun-10 3:24
Vitaliy Liptchinsky17-Jun-10 3:24 
QuestionArguments? Pin
Houssam Hamdan11-May-10 2:50
Houssam Hamdan11-May-10 2:50 
AnswerRe: Arguments? Pin
Vitaliy Liptchinsky11-May-10 3:18
Vitaliy Liptchinsky11-May-10 3:18 
GeneralRe: Arguments? Pin
Houssam Hamdan11-May-10 4:02
Houssam Hamdan11-May-10 4:02 
Questioncan i use it in a WCF service Pin
ATM@CodeProject23-Dec-09 18:46
ATM@CodeProject23-Dec-09 18:46 
AnswerRe: can i use it in a WCF service Pin
Vitaliy Liptchinsky24-Dec-09 1:50
Vitaliy Liptchinsky24-Dec-09 1:50 
QuestionDemo program bug? Pin
MrRoger7-May-09 9:48
MrRoger7-May-09 9:48 
Generalv2 Pin
andr___________11-Mar-09 22:14
andr___________11-Mar-09 22:14 
GeneralRe: v2 Pin
Vitaliy Liptchinsky11-Mar-09 22:53
Vitaliy Liptchinsky11-Mar-09 22:53 
Generalprogram hangs on exit [modified] Pin
andr___________4-Mar-09 5:16
andr___________4-Mar-09 5:16 
GeneralRe: program hangs on exit Pin
Vitaliy Liptchinsky5-Mar-09 0:05
Vitaliy Liptchinsky5-Mar-09 0:05 
GeneralRe: program hangs on exit Pin
andr___________5-Mar-09 3:22
andr___________5-Mar-09 3:22 
GeneralRe: program hangs on exit Pin
Vitaliy Liptchinsky5-Mar-09 4:49
Vitaliy Liptchinsky5-Mar-09 4:49 
GeneralRe: program hangs on exit Pin
Vitaliy Liptchinsky10-Mar-09 22:00
Vitaliy Liptchinsky10-Mar-09 22:00 
GeneralRe: program hangs on exit Pin
Houssam Hamdan16-Jun-10 22:32
Houssam Hamdan16-Jun-10 22:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.