我有一个应用程序,用户将选择执行许多任务以及最大线程数。每个任务应该在一个单独的线程上运行。这就是我要找的东西:
如果用户指定“n小于t”,其中n是最大线程数,t是任务数。该程序应运行“n”个线程,完成后,程序应通过某种方式通知并重复循环,直到所有任务完成。
我的问题是: 如何知道所有正在运行的线程已完成其工作,以便我可以重复循环。
答案 0 :(得分:9)
我建议您使用ThreadPool完成任务。它的算法通常比手动滚动更有效。
现在,当所有线程完成时,有趣的部分会收到通知。除非你确实有特定的需求使这个解决方案不合适,否则应该很容易用CountdownEvent类来实现,这是一种特殊的等待句,等待它被发出n
次信号。这是一个例子:
using System;
using System.Linq;
using System.Threading;
using System.Diagnostics;
namespace CSharpSandbox
{
class Program
{
static void SomeTask(int sleepInterval, CountdownEvent countDown)
{
try
{
// pretend this did something more profound
Thread.Sleep(sleepInterval);
}
finally
{
// need to signal in a finally block, otherwise an exception may occur and prevent
// this from being signaled
countDown.Signal();
}
}
static CountdownEvent StartTasks(int count)
{
Random rnd = new Random();
CountdownEvent countDown = new CountdownEvent(count);
for (int i = 0; i < count; i++)
{
ThreadPool.QueueUserWorkItem(_ => SomeTask(rnd.Next(100), countDown));
}
return countDown;
}
public static void Main(string[] args)
{
Console.WriteLine("Starting. . .");
var stopWatch = Stopwatch.StartNew();
using(CountdownEvent countdownEvent = StartTasks(100))
{
countdownEvent.Wait();
// waits until the countdownEvent is signalled 100 times
}
stopWatch.Stop();
Console.WriteLine("Done! Elapsed time: {0} milliseconds", stopWatch.Elapsed.TotalMilliseconds);
}
}
}
答案 1 :(得分:2)
您可能希望使用Thread Pool。您(可以)指定池中的线程数,并为其指定任务。当池中的线程空闲时,它会自动查找要执行的另一个任务。
答案 2 :(得分:2)
如果要在没有线程池的情况下执行此操作,可以使用Thread.Join
等待线程完成。那就是:
Thread t1 = new Thread(...);
Thread t2 = new Thread(...);
t1.Start();
t2.Start();
// Wait for threads to finish
t1.Join();
t2.Join();
// At this point, all threads are done.
当然,如果这是一个交互式应用程序,那么您希望它在线程本身中发生。如果你想得到想象,等待线程可以完成其中一个线程的工作(即你启动线程1,然后主线程将完成第二个线程的工作)。
如果这是一个交互式应用程序,那么您可能想要使用BackgroundWorker
(使用线程池)。如果将事件处理程序附加到RunWorkCompleted
事件,那么当工作人员完成其任务时,您将收到通知。如果您有多个工作人员,请拥有一个RunWorkCompleted
事件处理程序,并跟踪哪些工作人员已发出信号。当他们都发出信号时,你的程序就可以继续做其他任何需要做的事情。
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx的示例应该会给你一个良好的开端。
答案 3 :(得分:1)
你能检查每个线程的isAlive()值吗?如果所有值都等于false,那么您就会知道所有线程都已结束。此外,还有一种方法可让您的代表返回自己的状态。
http://msdn.microsoft.com/en-us/library/system.threading.thread.isalive(v=VS.90).aspx