在C#中有效管理线程

时间:2011-01-24 21:01:26

标签: c# multithreading

我有一个应用程序,用户将选择执行许多任务以及最大线程数。每个任务应该在一个单独的线程上运行。这就是我要找的东西:

如果用户指定“n小于t”,其中n是最大线程数,t是任务数。该程序应运行“n”个线程,完成后,程序应通过某种方式通知并重复循环,直到所有任务完成。

我的问题是: 如何知道所有正在运行的线程已完成其工作,以便我可以重复循环。

4 个答案:

答案 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