如何在创建和启动所有线程之前阻止新线程

时间:2013-08-08 07:45:39

标签: c# multithreading synchronization

我正在构建一个模拟赛马的小应用程序,以获得一些使用线程的基本技能。

我的代码包含此循环:

        for (int i = 0; i < numberOfHorses; i++)
        {
            horsesThreads[i] = new Thread(horsesTypes[i].Race);
            horsesThreads[i].Start(100);
        }

为了保持比赛“公平”,我一直在寻找一种方法让所有新创建的线程等到新线程的其余部分都被设置,然后才启动所有线程以开始运行他们的方法(请注意,据我所知,技术上线程无法在“同时”启动)

所以基本上,我正在寻找这样的东西:

        for (int i = 0; i < numberOfHorses; i++)
        {
            horsesThreads[i] = new Thread(horsesTypes[i].Race);
        }
        Monitor.LaunchThreads(horsesThreads);

3 个答案:

答案 0 :(得分:3)

线程不承诺公平或确定性结果,因此它不是模拟比赛的好方法。

话虽如此,但有一些同步对象可能会按照您的要求执行。我认为Barrier类(Fx 4+)就是你想要的。

答案 1 :(得分:1)

我会看ManualResetEvent作为门; 里面 Thread,递减一个计数器;如果它仍然不为零,请等待门;否则,打开大门。基本上是:

using System;    
using System.Threading;
class Program
{
    static void Main()
    {
        ManualResetEvent gate = new ManualResetEvent(false);
        int numberOfThreads = 10, pending = numberOfThreads;
        Thread[] threads = new Thread[numberOfThreads];
        ParameterizedThreadStart work = name =>
        {
            Console.WriteLine("{0} approaches the tape", name);
            if (Interlocked.Decrement(ref pending) == 0)
            {
                Console.WriteLine("And they're off!");
                gate.Set();
            }
            else gate.WaitOne();
            Race();
            Console.WriteLine("{0} crosses the line", name);
        };
        for (int i = 0; i < numberOfThreads; i++)
        {
            threads[i] = new Thread(work);
            threads[i].Start(i);
        }
        for (int i = 0; i < numberOfThreads; i++)
        {
            threads[i].Join();
        }
        Console.WriteLine("all done");

    }
    static readonly Random rand = new Random();
    static void Race()
    {
        int time;
        lock (rand)
        {
            time = rand.Next(500,1000);
        }
        Thread.Sleep(time);
    }

}

答案 2 :(得分:1)

Barrier类旨在支持此功能。

以下是一个例子:

using System;
using System.Threading;

namespace Demo
{
    class Program
    {
        private void run()
        {
            int numberOfHorses = 12;

            // Use a barrier with a participant count that is one more than the
            // the number of threads. The extra one is for the main thread,
            // which is used to signal the start of the race.

            using (Barrier barrier = new Barrier(numberOfHorses + 1))
            {
                var horsesThreads = new Thread[numberOfHorses];

                for (int i = 0; i < numberOfHorses; i++)
                {
                    int horseNumber = i;
                    horsesThreads[i] = new Thread(() => runRace(horseNumber, barrier));
                    horsesThreads[i].Start();
                }

                Console.WriteLine("Press <RETURN> to start the race!");
                Console.ReadLine();

                // Signals the start of the race. None of the threads that called
                // SignalAndWait() will return from the call until *all* the 
                // participants have signalled the barrier.

                barrier.SignalAndWait();

                Console.WriteLine("Race started!");
                Console.ReadLine();
            }
        }

        private static void runRace(int horseNumber, Barrier barrier)
        {
            Console.WriteLine("Horse " + horseNumber + " is waiting to start.");
            barrier.SignalAndWait();
            Console.WriteLine("Horse " + horseNumber + " has started.");
        }

        private static void Main()
        {
            new Program().run();
        }
    }
}

[编辑]我刚刚注意到Henk已经提到了Barrier,但我会在这里留下这个答案,因为它有一些示例代码。