c# 控制线程池。 运行 同时运行的线程多于预期

c# Controlled Thread Pooling. More threads are running simultaneously than expected

线程池和关键部分的第一个计时器。我正在尝试管理在任何给定时间处于活动状态的线程数。 MyThreadPool class 管理线程计数和活动线程。 MyUsefulWork 有线程访问的 square 方法。主要方法使用 ThreadPool.QueueUserWorkItem.

对工作进行排队

我正在使用 ManualResetEvent class 方法 Set() 和 WaitOne() 尝试将线程限制为最大计数 (MyThreadPool.MaxThreads),在此示例中为三个。但显然我做错了什么,因为我的 ActiveThreads 计数远远超过 MaxThreads 高达 18(在输出中显示为 'Increment: number' 或 'Decreement: number')。此外,活动线程在锁内递增,因此如果线程正在等待,则活动线程不会递增。

所以如果有人能指出我做错了什么,那将有很大帮助。谢谢。

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;
        }
    }       
}

输出结果如下

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

您忘记了 Reset() ManualResetEvent,它始终保持设置。

您可能想使用 AutoResetEvent 而不是 ManualResetEvent,请参阅 here