1

First timer to Threadpooling and critical sections. I'm trying to manage the number of threads that are active at any given time. MyThreadPool class manages the thread counts and active threads. MyUsefulWork has square method that is accessed by the threads. The main method queues the work using ThreadPool.QueueUserWorkItem.

I'm using ManualResetEvent class methods Set() and WaitOne() to try and limit the threads to max count(MyThreadPool.MaxThreads) which is three in this example. But apparently i'm doing something wrong, given that my ActiveThreads count is going way beyond the MaxThreads upto 18(which is displayed in output as 'Increment: number' or 'Decreement: number'). Also the activethreads is incremented within a lock so that if a thread is waiting, active thread is not incremented.

So if anyone can point out what I am doing wrong, it would be of great help. Thank you.

using System;
using System.Collections.Generic;
using System.Threading;

namespace ThreadingDemo
{
    class MyUsefulWork
    {
        public void Square(object number)
        {
            try
            {
                Console.WriteLine("Thread: {0} Square of {1} is {2}", Thread.CurrentThread.GetHashCode(), number, Math.Pow(Convert.ToDouble(number), 2));
                Thread.Sleep(2000);
                Console.WriteLine("Thread for {0} woke up", number);
            }
            catch { }
            finally
            {
                MyThreadPool.ThreadFinishedWork();
            }
        }
    }

    public static class MyThreadPool
    {
        private static int ActiveThreads { get; set; }
        private static int MaxThreads { get; set; }
        public static ManualResetEvent Mre { get; set; }
        public static Object IncrementLock { get; set; }
        public static Object DecreementLock { get; set; }

        public static void SetMaxThreads(int maxThreads)
        {
            MaxThreads = maxThreads;
        }
        public static int GetMaxThreads()
        {
            return MaxThreads;
        }
        public static void ThreadStartedWork()
        {
            SetWait();
        }
        public static void ThreadFinishedWork()
        {
            ActiveThreads--;
            ReleaseWait();
        }
        private static void SetWait()
        {
            lock (IncrementLock)
            {
                ActiveThreads++;
                Console.WriteLine("Increment: {0}", ActiveThreads);
                if (ActiveThreads >= MaxThreads)
                    Mre.WaitOne(Timeout.Infinite, true);
            }
        }
        private static void ReleaseWait()
        {
            lock (DecreementLock)
            {
                Console.WriteLine("Decreement: {0}", ActiveThreads);
                if (ActiveThreads < MaxThreads)
                    Mre.Set();
            }
        }
    }

    class Program
    {
        public static int Main(string[] args)
        {
            var myUsefulWork = new MyUsefulWork();
            var inputs = new List<string>();

            MyThreadPool.Mre = new ManualResetEvent(false);
            MyThreadPool.IncrementLock = new object();
            MyThreadPool.DecreementLock = new object();
            MyThreadPool.SetMaxThreads(3);

            for (var i = 1; i <= 20; i++)
                inputs.Add(i.ToString());

            for (int iItem = 1; iItem <= 20; iItem++)
            {
                Console.WriteLine("Queue to Thread Pool {0}", iItem);
                MyThreadPool.ThreadStartedWork();
                ThreadPool.QueueUserWorkItem(new WaitCallback(myUsefulWork.Square), iItem.ToString());
            }
            Console.ReadKey();
            return 0;
        }
    }       
}

The output is as follows.

Queue to Thread Pool 1
Increment: 1
Queue to Thread Pool 2
Increment: 2
Queue to Thread Pool 3
Increment: 3
Thread: 6 Square of 1 is 1
Thread: 11 Square of 2 is 4
Thread for 1 woke up
Decreement: 2
Queue to Thread Pool 4
Increment: 3
Thread: 12 Square of 3 is 9
Queue to Thread Pool 5
Increment: 4
Queue to Thread Pool 6
Increment: 5
Queue to Thread Pool 7
Increment: 6
Queue to Thread Pool 8
Increment: 7
Thread: 6 Square of 4 is 16
Queue to Thread Pool 9
Increment: 8
Queue to Thread Pool 10
Increment: 9
Queue to Thread Pool 11
Increment: 10
Queue to Thread Pool 12
Increment: 11
Queue to Thread Pool 13
Increment: 12
Queue to Thread Pool 14
Increment: 13
Thread for 2 woke up
Decreement: 12
Thread: 11 Square of 5 is 25
Queue to Thread Pool 15
Increment: 13
Queue to Thread Pool 16
Increment: 14
Queue to Thread Pool 17
Increment: 15
Queue to Thread Pool 18
Increment: 16
Queue to Thread Pool 19
Increment: 17
Queue to Thread Pool 20
Increment: 18
Thread: 13 Square of 6 is 36
Thread: 14 Square of 7 is 49
Thread for 3 woke up
Decreement: 17
Thread for 4 woke up
Decreement: 16
Thread: 6 Square of 9 is 81
Thread: 12 Square of 8 is 64
Thread for 5 woke up
Decreement: 15
Thread: 11 Square of 10 is 100
Thread: 15 Square of 11 is 121
Thread for 6 woke up
Decreement: 14
Thread: 13 Square of 12 is 144
Thread for 7 woke up
Decreement: 13
Thread: 14 Square of 13 is 169
Thread for 9 woke up
Decreement: 12
Thread: 6 Square of 14 is 196
Thread for 8 woke up
Decreement: 11
Thread: 12 Square of 15 is 225
Thread for 10 woke up
Decreement: 10
Thread: 11 Square of 16 is 256
Thread for 11 woke up
Decreement: 9
Thread: 15 Square of 17 is 289
Thread for 12 woke up
Decreement: 8
Thread: 13 Square of 18 is 324
Thread for 13 woke up
Decreement: 7
Thread: 14 Square of 19 is 361
Thread for 14 woke up
Decreement: 6
Thread: 6 Square of 20 is 400
Thread for 15 woke up
Decreement: 5
Thread for 16 woke up
Decreement: 4
Thread for 17 woke up
Decreement: 3
Thread for 18 woke up
Decreement: 2
Thread for 19 woke up
Decreement: 1
Thread for 20 woke up
Decreement: 0
Pazza22
  • 554
  • 3
  • 18

1 Answers1

2

You forgot to Reset() the ManualResetEvent, it always stays set.

You probably want to use an AutoResetEvent instead of the ManualResetEvent, see here

Community
  • 1
  • 1
thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110