Mou
Mou

Reputation: 16312

Multiple thread using ThreadPool and use of CountdownEvent

i got a example of CountdownEvent usage but when i go through the sample code then i just do not understand what it is doing and how CountdownEvent's Signal() and AddCount() help to synchronization for multiple thread.

here is the sample. please some one help me to understand how synchronization is working for multiple thread in this example where Signal() and AddCount() used.

class Program
{
    static void Main(string[] args)
    {
        using (CountdownEvent e = new CountdownEvent(1))
        {
            // fork work: 
            for (int i = 1; i <= 5;i++ )
            {
                // Dynamically increment signal count.
                TaskInfo ti = new TaskInfo("Current Thread ", i);
                Console.WriteLine("Running thread " + e.CurrentCount);
                e.AddCount();
                ThreadPool.QueueUserWorkItem(delegate(object state)
                {
                    try
                    {
                        //ProcessData(state);
                        TaskInfo inner_ti = (TaskInfo)state;
                        //Console.WriteLine(inner_ti.Boilerplate + inner_ti.Value);
                        Thread.Sleep(2000);
                    }
                    finally
                    {
                        Console.WriteLine("Signal thread " + e.CurrentCount);
                        e.Signal();
                    }
                },
                 ti);
            }
            Console.WriteLine("Outer Signal thread " + e.CurrentCount);
            e.Signal();

            // The first element could be run on this thread. 

            // Join with work.
            Console.WriteLine("Wait thread ");
            e.Wait();
            Console.WriteLine("ReadLine..... ");
            Console.ReadLine();
        }
    }
}

public class TaskInfo
{
    // State information for the task.  These members 
    // can be implemented as read-only properties, read/write 
    // properties with validation, and so on, as required. 
    public string Boilerplate;
    public int Value;

    // Public constructor provides an easy way to supply all 
    // the information needed for the task. 
    public TaskInfo(string text, int number)
    {
        Boilerplate = text;
        Value = number;
    }
}

just guide me with small sample code like how Signal() and AddCount() is used in real life scenario for thread synchronization. thanks

Upvotes: 1

Views: 1376

Answers (1)

Peter Duniho
Peter Duniho

Reputation: 70701

The job of CountdownEvent is to provide a waitable object (i.e. an object that will block the current thread on request until some condition is satisfied), where the condition that needs to be satisfied is for the object's internal counter to reach the value of 0.

The code you've shown will initialize the CountdownEvent object with a count of 1. This value represents the main thread itself; the main thread will call Signal() later, indicating that it's completed its own work (which is to start five other threads).

For each new task that is created, the main thread increments — by calling the AddCount() method — the CountdownEvent object's counter by one before starting that new task (in this case, by queuing the task to the global thread pool). Each task, as it completes, will then decrement the object's counter by calling the Signal() method.

So initially, the code is repeatedly increasing the counter, from its initial value of 1, to its maximum value of 6.

Immediately after the tasks have been queued, the main thread decrements the counter to 5. Each task, as it completes, decrements the counter again. Five tasks means decrementing the counter five times, so when the last task completes, the counter will reach 0.

Remember: the point of the CountdownEvent object is to release a thread that is waiting on it when its internal counter reaches 0. (Or more specifically, for the waitable object to be set to its signaled, non-blocking state).

The main thread calls the Wait() method on the CountdownEvent object, which initially causes the main thread to be blocked (i.e. to wait). It will continue to wait until the CountdownEvent is set to the non-blocking state, which occurs when its internal counter reaches 0, which occurs when the last task completes.

Thus, the main thread waits until the last task completes.

just guide me with small sample code like how Signal() and AddCount() is used in real life scenario for thread synchronization

The code example you've posted here seems "real" enough. My description above explains how the code example works. You would use the CountdownEvent object in any scenario where you have some specific count of operations, tasks, events, etc. that should occur before some specific thread should continue after waiting.

Of course, not all synchronization scenarios involve this kind of requirement. There are other, different synchronization mechanisms that can be used for those other scenarios. The CountdownEvent is specifically for those scenarios where the waiting of a thread is unblocked by the completion of a countdown, hence the name of the class.

Upvotes: 2

Related Questions