2013-05-13 3 views
0

Я смотрю этот сайт для threads. Я играл с кодом, чтобы ответить на вопрос: «Does CountdownEvent остановить все потоки?» ответа у меня нет. Затем я решил сыграть с номером, который передается в CountdownEvent. Вот мой кодCountDownEvent не будет ждать, пока все сигналы не будут вызваны

namespace ThreadPractice 
{ 
    class Program 
    { 
     static CountdownEvent CountDown = new CountdownEvent(4); 
     static void Main() 
     { 
      new Thread(() => SaySomething("I am Thread one.")).Start(); 
      new Thread(() => SaySomething("I am thread two.")).Start(); 
      new Thread(() => SaySomethingElse("Hello From a different Thread")).Start(); 
      new Thread(() => SaySomething("I am Thread Three.")).Start(); 
      CountDown.Wait(); 
      Console.Read(); 
     } 

     static void SaySomething(string Something) 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine(Something); 
      CountDown.Signal(); 
     } 

     static void SaySomethingElse(string SomethingElse) 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine(SomethingElse); 
     } 
    } 
} 

Я ожидаю, что поток, вызывающий SaySomethingELse() для выполнения, но остальные потоки выполняются так же, даже если только четыре сигналы были вызваны.

Почему это так?

Спасибо,

dhoehna

+1

Почему вы ожидали бы другие темы * не * для выполнения? Только ваш основной поток использует 'Wait'. Остальные просто * сигнализируют * обратный отсчет. –

+1

Я бы ожидал, что все потоки будут запускать и печатать что-то, а затем для вашей программы блокировать навсегда вызов 'CountDown.Wait()'. Точкой отсчета является блокировка * одного потока *, пока куча других потоков не сообщит, что безопасно продолжать. – dlev

+0

@dlev Что случилось, так это то, что я забыл вызвать wait на всех потоках. Я подумал, что ждать было простое заявление. –

ответ

3

Он смотрит на меня, как вы получили Signal и Wait навыворот. Если вы хотите, чтобы звонки SaySomething дождались обратного отсчета до 0, вы должны позвонить Wait. Вот пример:

using System; 
using System.Threading; 

namespace ThreadPractice 
{ 
    class Program 
    { 
     static CountdownEvent CountDown = new CountdownEvent(4); 
     static void Main() 
     { 
      new Thread(() => SaySomething("I am Thread one.")).Start(); 
      new Thread(() => SaySomething("I am thread two.")).Start(); 
      new Thread(() => SaySomethingElse("Hello From a different Thread")).Start(); 
      new Thread(() => SaySomething("I am Thread Three.")).Start(); 
      for (int i = 0; i < 4; i++) 
      { 
       Console.WriteLine("Calling Signal (time #{0})", i); 
       CountDown.Signal(); 
       Thread.Sleep(1000); 
      } 
      Console.WriteLine("Done"); 
     } 

     static void SaySomething(string Something) 
     { 
      CountDown.Wait(); 
      Console.WriteLine(Something); 
     } 

     static void SaySomethingElse(string SomethingElse) 
     { 
      Thread.Sleep(1000); 
      Console.WriteLine(SomethingElse); 
     } 
    } 
} 

Выход:

Calling Signal (time #0) 
Hello From a different Thread 
Calling Signal (time #1) 
Calling Signal (time #2) 
Calling Signal (time #3) 
I am Thread one. 
I am Thread Three. 
I am thread two. 
Done 
+0

Я понимаю. Ваш цикл for называется wait в каждом потоке. Поэтому, чтобы заблокировать поток в отношении таймера обратного отсчета, мне нужно вызвать wait для каждого потока. Спасибо много. –

1

Хммм ... он смотрит на меня, как вы хотите, чтобы ждать, пока все нити, чтобы закончить, прежде чем продолжить в главном потоке. Если это так, вы забыли Signal() в SaySomethingElse(). Это не позволяет CountDown.CurrentCount достигать 0 (ноль), и поэтому ваш основной поток «застревает». Вы устанавливаете его на 4, и он уменьшается до 1 (один). Исправить это, и вы должны получить желаемое? Результаты:

class Program 
{ 
    static CountdownEvent CountDown = new CountdownEvent(4); 
    static void Main() 
    { 
     new Thread(() => SaySomething("I am Thread one.")).Start(); 
     new Thread(() => SaySomething("I am thread two.")).Start(); 
     new Thread(() => SaySomethingElse("Hello From a different Thread")).Start(); 
     new Thread(() => SaySomething("I am Thread Three.")).Start(); 

     CountDown.Wait(); 

     Console.WriteLine("Done!"); 
     Console.Read(); 
    } 

    static void SaySomething(string Something) 
    { 
     Thread.Sleep(1000); 
     Console.WriteLine(Something); 
     CountDown.Signal(); 
    } 

    static void SaySomethingElse(string SomethingElse) 
    { 
     Thread.Sleep(1000); 
     Console.WriteLine(SomethingElse); 
     CountDown.Signal(); 
    } 
} 

Выход:

I am Thread one. 
I am thread two. 
Hello From a different Thread 
I am Thread Three. 
Done! 
+0

Спасибо, но это противоположность тому, что я искал. Это не то, что я хочу, чтобы потоки подождали. Это было то, что я поставил Countdown на четыре, и я использовал только три сигнала, а потоки все еще выполнялись. Мне было интересно, почему это произошло. Я хотел остановить выполнение потока, потому что я установил таймер обратного отсчета в 4 и сделал только три сигнала. –

+0

Нить (ы), которая фактически вызывает Wait(), является той, которая останавливается. В исходном коде это был основной поток. Он сделал именно то, что должен, остановился, так как счетчик не достиг нулевого уровня. Другие потоки - это просто обычные потоки, которые выполняются сами по себе. Calling Signal() не влияет на то, как они работают, он просто уменьшает счетчик. Пример Джона перевернул его и заставил каждый отдельный поток ждать, пока счетчик не будет равен нулю, а не ожидает основного потока. Основной поток сигнализировал достаточно времени, чтобы другие потоки продолжались. Рад, что вы все разобрались. –

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