2

I am looking at this site for threads. I have been playing with the code to answer the question "Does the CountdownEvent stop all threads?" the answer I got was no. Then I decided to play with the number that is passed into the CountdownEvent. Here is my code

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

I am expecting that the thread that calls SaySomethingELse() to execute but the other threads execute as well even though only four signals have been called.

Why does it do that?

Thanks,

dhoehna

Darren Hoehna
  • 269
  • 2
  • 8
  • 19
  • 1
    Why would you expect the other threads *not* to execute? Only your main thread is using `Wait`. The others are just *signalling* the count-down. – Jon Skeet May 13 '13 at 19:56
  • 1
    I would expect all the threads to run and print something and then for your program to block forever on the `CountDown.Wait()` call. The point of the countdown is to block *one thread* until a bunch of other threads have signaled that it is safe to continue. – dlev May 13 '13 at 19:57
  • @dlev What was wrong is that I forgot to call wait on all the threads. I thought wait was a blanket statement. – Darren Hoehna May 14 '13 at 14:48

2 Answers2

6

It looks to me like you've got Signal and Wait the wrong way round. If you want the SaySomething calls to wait for the countdown to reach 0, you should be calling Wait. Here's an example:

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

Output:

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
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • I understand. Your for loop called wait on each thread. So in order to block a thread with respect to the countdown timer I need to call wait on each thread. Thank you much. – Darren Hoehna May 14 '13 at 14:47
1

Hmmm...it looks to me like you want to wait for all the threads to finish before continuing on in the main thread. If so, you forgot to Signal() in SaySomethingElse(). This prevents CountDown.CurrentCount from reaching 0 (zero) and is why your main thread is "stuck" You set it to 4 and it only goes down to 1 (one). Fix it and you should get the desired? results:

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

Output:

I am Thread one.
I am thread two.
Hello From a different Thread
I am Thread Three.
Done!
Idle_Mind
  • 38,363
  • 3
  • 29
  • 40
  • Thanks but that is the opposite of what I was looking for. It's not that I want the threads to wait. It was that I set Countdown to four and I only used three signals and the threads still executed. I was wondering why that happened. I wanted to stop the thread from executing because I set the countdown timer to 4 and only made three signal calls. – Darren Hoehna May 14 '13 at 14:45
  • The thread(s) that actually calls Wait() is the one that halts. In your original code, that was the main thread. It did exactly what it should, stopping since the counter didn't reach zero. The other threads are just normal threads that execute on their own. Calling Signal() doesn't affect how they run, it just decrements the count. Jon's example flipped it and made each individual thread wait until the count was zero, instead of the main thread waiting. The main thread signaled enough times to allow the other threads to continue. Glad you've got it all sorted out. – Idle_Mind May 14 '13 at 14:59