2013-08-08 3 views
3

Я создаю небольшое приложение, имитирующее скачки, чтобы получить некоторые базовые навыки в работе с потоками.Как заблокировать новые потоки, пока не будут созданы и запущены все потоки

Мой код содержит этот цикл:

 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); 
+0

Вы можете использовать TPL и настроить список задач? если вы специально не хотите учиться этому? – christiandev

+0

В новой среде .net у вас есть ключевое слово async. Word cheching для обновления ваших навыков. – lordkain

+0

@lordkain, который, однако, не имеет ничего общего с этим сценарием. –

ответ

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(); 
     } 
    } 
} 

[EDIT] Я просто заметил, что Хенк уже упоминалось Barrier, но я оставлю этот ответ здесь, потому что у него есть некоторые примеры кода.

3

Threading не обещает справедливости или детерминированных результатов, поэтому это не очень хороший способ имитировать гонку.

Сказав это, есть некоторые объекты синхронизации, которые могут делать то, что вы просите. Я думаю, что класс Barrier (Fx 4+) - это то, что вы хотите.

+0

Это небольшое приложение - это упражнение, которое я нашел в Интернете, и он специально поручает мне установить нить для каждой лошади. Код может оставаться таким, каким он есть сейчас. Мне кажется, что если поток начинает работать до того, как все его параллели были созданы, приложение не сможет имитировать реальную гонку. – AdiB

+0

После того, как вы установили, что (с барьером) ваше приложение все равно «не сможет имитировать реальную гонку». Но для упражнений все в порядке. –

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); 
    } 

} 
Смежные вопросы