一旦第一组工作线程完成处理,我如何使用 AutoResetEventHandler 向主线程函数发出信号以再次启动线程
Posted
技术标签:
【中文标题】一旦第一组工作线程完成处理,我如何使用 AutoResetEventHandler 向主线程函数发出信号以再次启动线程【英文标题】:How can i use AutoResetEventHandler to signal Main thread function to start threads again once the first set of worker threads are done processing 【发布时间】:2013-01-14 01:42:18 【问题描述】:要求:- 在任何给定时间点,只有 4 个线程应该调用四个不同的函数。一旦这些线程完成,下一个可用线程应该调用相同的函数。
当前代码:- 这似乎是实现此类目标的最糟糕的方法。 While(True) 会导致不必要的 CPU 峰值,运行以下代码时我可以看到 CPU 上升到 70%。
问题:-我如何使用 AutoResetEventHandler 向主线程 Process() 函数发出信号,以便在前 4 个工作线程完成处理后再次启动下一个 4 个线程,而不会浪费 CPU 周期。请推荐
public class Demo
object protect = new object();
private int counter;
public void Process()
int maxthread = 4;
while (true)
if (counter <= maxthread)
counter++;
Thread t = new Thread(new ThreadStart(DoSomething));
t.Start();
private void DoSomething()
try
Thread.Sleep(50000); //simulate long running process
finally
lock (protect)
counter--;
【问题讨论】:
您能告诉我们更多关于您为什么要这样做的信息吗?我问是因为 .Net 框架可能已经支持更好的解决方案。 我被要求分析此代码并提供更好的方法来完成此操作,以便防止 CPU 峰值。 【参考方案1】:您可以使用TPL 以更简单的方式实现您想要的。如果您运行下面的代码,您会注意到每个线程终止后都会写入一个条目,并且只有在所有四个线程都终止后才会写入 "Finished batch"
条目。
此示例使用Task.WaitAll
等待所有任务完成。该代码使用无限循环仅用于说明目的,您应根据您的要求计算hasPendingWork
条件,以便仅在需要时启动新的一批任务。
例如:
private static void Main(string[] args)
bool hasPendingWork = true;
do
var tasks = InitiateTasks();
Task.WaitAll(tasks);
Console.WriteLine("Finished batch...");
while (hasPendingWork);
private static Task[] InitiateTasks()
var tasks = new Task[4];
for (int i = 0; i < tasks.Length; i++)
int wait = 1000*i;
tasks[i] = Task.Factory.StartNew(() =>
Thread.Sleep(wait);
Console.WriteLine("Finished waiting: 0", wait);
);
return tasks;
另一件事,从您问题的文本要求部分,我相信一批四个新线程应该只在之前的四个线程完成后才开始。但是,您发布的代码与该要求不兼容,因为它在前一个线程终止后立即启动一个新线程。你应该明确你的要求到底是什么。
更新:
如果您想在四个线程之一终止后立即启动一个线程,您仍然可以使用 TPL 而不是显式启动新线程,但您可以使用 SemaphoreSlim
将正在运行的线程数限制为四个。例如:
private static SemaphoreSlim TaskController = new SemaphoreSlim(4);
private static void Main(string[] args)
var random = new Random(570);
while (true)
// Blocks thread without wasting CPU
// if the number of resources (4) is exhausted
TaskController.Wait();
Task.Factory.StartNew(() =>
Console.WriteLine("Started");
Thread.Sleep(random.Next(1000, 3000));
Console.WriteLine("Completed");
// Releases a resource meaning TaskController.Wait will unblock
TaskController.Release();
);
【讨论】:
已更新要求。提供的代码正是需要做的。感谢您指出。以上是关于一旦第一组工作线程完成处理,我如何使用 AutoResetEventHandler 向主线程函数发出信号以再次启动线程的主要内容,如果未能解决你的问题,请参考以下文章