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
线程池和关键部分的第一个计时器。我正在尝试管理在任何给定时间处于活动状态的线程数。 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