在一个类实例上进行线程化,如何等待所有线程完成?

时间:2012-05-25 15:30:45

标签: c# threadpool

请考虑以下代码。我不想创建class Waiter的多个实例。 (所以我不能使用ManualResetEvent类)

using System;
using System.Threading;

    public class Waiter
    {
        static int counter=0;
        static int max=20;

        public void Start()
        {
            for (int i = 1; i <= max; i++)
            {
                ThreadPool.QueueUserWorkItem(DoWork, (object)i);

            }
            Console.Read();//without this line the application quits before all threads are complete :(

        }

        public void DoWork(object o)
        {
            try
            {
                Thread.Sleep(1000);

            }
            finally
            {
                counter++;
                Console.WriteLine(counter);
                if (counter==max )
                {
                    Console.WriteLine("All threads complete");
                }
            }



        }

    }

    public class ThreadPoolExample
    {
        static void Main()
        {

            Waiter wtr=new Waiter();
            wtr.Start();



        }
    }

我对上面的代码有两个问题

1&gt;没有Console.Read()应用程序在所有线程结束之前退出。

2&gt;语句Console.WriteLine("All threads complete");执行两次。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

改为使用Tasks,然后您可以执行Task.WaitAll(tasks);

此外,通过工厂实例化您的任务:

Task.Factory.StartNew(() => { Console.Writeline(""); });

它将为您使用线程池。

答案 1 :(得分:0)

您应该使用Interlocked.Increment来增加counter。因为当两个线程试图同时递增它时存在竞争条件。

如果您想让多个Writer实例同时工作,那么您就不能拥有静态counter变量。他们会互相争斗。只需将其设为私有实例变量即可。 Max应该是constreadonly(并保持静态),如果它永远不会改变,或者它也应该是一个实例字段,如果它可以改变。

最后,如果你有一个非静态ManualResetEvent实例,你可以在Start中创建它,初始化它以设置,在循环结束时等待它,然后在最后一个线程完成(你当前只是写入控制台)。