简体   繁体   English

c#控制线程池。 同时运行的线程数量超过预期

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

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. MyThreadPool类管理线程计数和活动线程。 MyUsefulWork has square method that is accessed by the threads. MyUsefulWork具有线程可以访问的平方方法。 The main method queues the work using ThreadPool.QueueUserWorkItem. 主要方法使用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. 我正在使用ManualResetEvent类方法Set()和WaitOne()尝试将线程限制为最大数量(MyThreadPool.MaxThreads),在此示例中为三个。 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'). 但是显然我做错了,因为我的ActiveThreads计数已经超过了MaxThreads的18(在输出中显示为“ Increment:number”或“ 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

You forgot to Reset() the ManualResetEvent , it always stays set. 您忘记了Reset() ManualResetEvent ,它始终保持设置状态。

You probably want to use an AutoResetEvent instead of the ManualResetEvent , see here 您可能要使用AutoResetEvent而不是ManualResetEvent ,请参见此处

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM