none
ThreadPool: Key points/Issues to remember while implementation RRS feed

  • General discussion

  • I have come across a threading implementation where many number of thread needs to be spawned from a WCF application to another web service. I have evaluated spawning individual threads Vs using ThreadPool. Here are exert on ThreadPool.

    The ThreadPool class provides your application with a pool of worker threads that are managed by the system, allowing you to concentrate on application tasks rather than thread management.

    Code Snip

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ThreadPool1
    {
        class Program
        {
            const int CapitalStartCharIndex = 65;
            const int LowarStartCharIndex = 97;
    
            static void Main(string[] args)
            {
                List<Learner> learnerList = new List<Learner>();
                //int wt, pt;
                //ThreadPool.SetMaxThreads(30, 5);
                
                for (int i = 0; i <= 25; i++)
                {
                    Random r = new Random();
                    Learner learner = new Learner(System.Convert.ToChar(CapitalStartCharIndex + i), i, System.DateTime.Now);
                    Console.WriteLine("Main thread {0} - {1} {2} ", learner.FirstName, learner.Id, learner.CreationTime.ToString());
                    learnerList.Add(learner);
                    ThreadPool.QueueUserWorkItem(new WaitCallback(ProcessLearner),learnerList.ElementAt(i));                
                    //Thread.Sleep(r.Next(100));
                }
                Console.Read();
    
                foreach (Learner learner in learnerList)
                {
                    Console.WriteLine("Result : {0} - {1} - {2} {3} ", learner.FirstName, learner.Id.ToString(), learner.CreationTime.ToString(), learner.ProcessedFirstName);          
                }
                Console.Read();
                Console.Read();
            }
    
    
            static void ProcessLearner(object data)
            {            
                Learner learner = (Learner)data;
                learner.ProcessedFirstName = System.Convert.ToChar(LowarStartCharIndex + learner.Id);            
                Random r = new Random();
                learner.RandomWait = r.Next(10000000);
                Console.WriteLine("Learner Thread pool : {0} - {1} - {2} {3} {4} ", learner.FirstName, learner.Id.ToString(), learner.CreationTime.ToString(), learner.ProcessedFirstName, learner.RandomWait);            
            }
        }
    
        class Learner
        {
            public Learner(char name, int id, DateTime time)
            {
                FirstName = name;
                Id = id;
                CreationTime = time;
    
            }
            public char FirstName;
            public char ProcessedFirstName;
            public int Id;
            public DateTime CreationTime;
            public int RandomWait;
        }
    }


    Key Points

    When not to use thread pool:

    There are several scenarios in which it is appropriate to create and manage your own threads instead of using thread pool threads:

    • You require a foreground thread.
    • 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

    Issues

    1. When the thread pool reuses a thread, it does not clear the data in thread local storage or in fields that are marked with the ThreadStaticAttribute attribute. Therefore, data that is placed in thread local storage by one method can be exposed to any other method that is executed by the same thread pool thread. A method that accesses a field that is marked with the ThreadStaticAttribute attribute could encounter different data depending on which thread pool thread executes it.
    2. You can also queue work items that are not related to a wait operation to the thread pool. To request that a work item be handled by a thread in the thread pool, call the QueueUserWorkItem method. This method takes as a parameter a reference to the method or delegate that will be called by the thread selected from the thread pool. There is no way to cancel a work item after it has been queued.

    Kindly note that the code snap is only for trial and research purpose.

    I hope this helps!

    Monday, August 6, 2012 3:19 PM

All replies

  • Note that .NET 4 addresses both of these issues.

    1) You can use ThreadLocal<T> instead of ThreadStaticAttribute.  This allows deterministic cleanup (via Dispose) of all resources used by all threads.

    2) By using Task.Factory.StartNew instead of QueueUserWorkItem, you still get the advantages of using the ThreadPool, but can provide a CancelationToken, and cancel via the CancelationTokenSource.  This allows you to cancel a work item after it's been queued.


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Monday, August 6, 2012 3:56 PM
    Moderator
  • That's right Mr Reed! Thanks for the valuable input!

    The issues I shared as a preventive measure to avoid same kind of repetitive mistakes while implementing ThreadPool!

    Tuesday, August 7, 2012 8:43 AM