【问题标题】:c# Controlled Thread Pooling. More threads are running simultaneously than expectedc# 受控线程池。同时运行的线程多于预期
【发布时间】:2015-03-28 18:36:23
【问题描述】:

线程池和临界区的第一个计时器。我正在尝试管理在任何给定时间处于活动状态的线程数。 MyThreadPool 类管理线程计数和活动线程。 MyUsefulWork 具有由线程访问的 square 方法。 main 方法使用 ThreadPool.QueueUserWorkItem 对工作进行排队。

我正在使用 ManualResetEvent 类方法 Set() 和 WaitOne() 来尝试将线程限制为最大计数(MyThreadPool.MaxThreads),在本示例中为 3。但显然我做错了什么,因为我的 ActiveThreads 计数超出了 MaxThreads 最多 18 个(在输出中显示为“增量:数字”或“减量:数字”)。此外,活动线程在锁内递增,因此如果线程正在等待,则活动线程不会递增。

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

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

【问题讨论】:

    标签: c# multithreading locking threadpool critical-section


    【解决方案1】:

    您忘记了Reset() ManualResetEvent,它始终保持不变。

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

    【讨论】:

    • 谢谢 Thumbmunkeys。 AutoResetEvent 就像一个魅力。你可能救了我的星期天;)
    猜你喜欢
    • 2019-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-28
    • 1970-01-01
    • 1970-01-01
    • 2011-08-27
    相关资源
    最近更新 更多