October 23, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Create Your Own Thread Pool

  • November 10, 2008
  • By Chris Bennett
  • Send Email »
  • More Articles »

If you build many .NET applications where you need to perform regular work such as packet processing from a socket, you may have run into some of the drawbacks in the built-in System.Threading.ThreadPool. A major limitation of this class is that it is static, which means that an application can have one and only one ThreadPool. The .NET framework itself also uses this ThreadPool for items such as the Timer in the System.Threading namespace. In the end, this means that if you need to use a thread pool in your application and you choose to use the existing .NET class, you will not have full control over it. To overcome this limitation, the simplest solution is to create your own thread pool.

Support Items

To create the thread pool, you first need to build a WorkItem class used to define work submitted to the thread pool and a delegate to process the work. This code is listed below:

public delegate void WorkDelegate(object WorkObject);

class WorkItem
{
   public object WorkObject;
   public WorkDelegate Delegate;
}

MyThreadPool Class

Next, you need to create a MyThreadPool class, which is the main class used to interact with the thread pool. Listed below are the fields and properties for the MyThreadPool class.

private int m_MinThreads=0;
public int MinThreads
{
   get
   {
      return this.m_MinThreads;
   }
   set
   {
      this.m_MinThreads = value;
   }
}

private int m_MaxThreads=100;
public int MaxThreads
{
   get
   {
      return this.m_MaxThreads;
   }
   set
   {
      this.m_MaxThreads = value;
   }
}

private int m_IdleTimeThreshold=5;
public int IdleTimeThreshold
{
   get
   {
      return this.m_IdleTimeThreshold;
   }
   set
   {
      this.m_IdleTimeThreshold = value;
   }
}

The MinThreads/MaxThreads properties are used to control the number of threads used to process the work. The IdleTimeThreshold is used to determine how many seconds a thread should be allowed to sit idle prior to shutting it down.

Next, you dig further into extending the MyThreadPool class with the following properties.

private Queue<WorkItem> WorkQueue;
public int QueueLength
{
   get
   {
      return WorkQueue.Count();
   }
}

private List<WorkThread> ThreadList;
private Thread ManagementThread;
private bool KeepManagementThreadRunning = true;

The WorkQueue shown above is the main queue used to process work in first-in, first out (FIFO) order. Entries stored in the queue are of type WorkItem as defined above. The ThreadList maintains the current list of active threads used to process WorkItems. The ManagementThread is used for performing control functions on the thread pool, such as shutting down idle threads. Next, you'll take a look at the public method used to submit work to the thread pool.

public void QueueWork(object WorkObject, WorkDelegate Delegate)
{
   WorkItem wi = new WorkItem();
   wi.WorkObject = WorkObject;
   wi.Delegate = Delegate;
   lock (WorkQueue)
   {
      WorkQueue.Enqueue(wi);
   }

   //Now see if there are any threads that are idle
   bool FoundIdleThread = false;
   foreach (WorkThread wt in ThreadList)
   {
      if (!wt.Busy)
      {
         wt.WakeUp();
         FoundIdleThread = true; break;
      }
    }

   if (!FoundIdleThread)
   {
      //See if we can create a new thread to handle the
      //additional workload
      if (ThreadList.Count < m_MaxThreads)
      {
         WorkThread wt = new WorkThread(ref WorkQueue);
         lock (ThreadList)
         {
            ThreadList.Add(wt);
         }
      }
   }
}

The method above, QueueWork, is used to submit work to be processed. The QueueWork method first submits the WorkItem to the WorkQueue. Then, the method tries to locate an idle thread in the ThreadList. If an idle thread was not located and the Thread List count is less than the MaxThreads value, the method attempts to launch a new thread. The advantage of starting additional threads in the QueueWork method is that the thread pool will be able to ramp up the number of threads very quickly as work is submitted. Because you are dealing with multiple threads accessing many of the objects, you need to make sure you take the necessary precautions to lock variable to prevent data corruption in the WorkQueue and ThreadList.





Page 1 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel