Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return to zero CountdownEvent

I'm trying to use a CountdownEvent to only allow threads to continue when the event's count is zero, however I would like the initial count to be zero. In effect I'd like a return to zero behaviour whereby the event is signalled whenever the count is zero and threads are made to wait whenever it's greater than zero.

I can initialize a Countdown event with 0 initial count but when I try to add to the count I get InvalidOperationException "CountdownEvent_Increment_AlreadyZero" .

Is there an alternative class or another way that I can use Countdown event in order to avoid this limitation?

like image 804
chillitom Avatar asked Dec 08 '10 13:12

chillitom


1 Answers

Edit

public void Dispatch()
{
    using (var ev = new CountdownEvent(1))
    {
        foreach (var task in <collection_of_tasks_to_start>)
        {
            ev.AddCount();
            // start *task* here. Don't forget to pass *ev* to it!
        }

        ev.Signal();
        ev.Wait();
    }
}

// task code
void Handler(CountdownEvent ev)
{
    try
    {
        // do task logic
    }
    finally
    {
        ev.Signal();
    }
}

Why and how this works?

  1. If you haven't spawned any tasks
    • nothing will happen and Dispatch will just finish normally.
    • ev.Signal makes sure that once ev.Wait is called, initial value of the counter is 0 and Wait will not block execution
  2. If you spawned at least one task
    • we have two cases to consider: fast- and slow-running tasks and understand how they affect execution at point where ev.Wait() is called.
      • fast tasks, i.e. tasks that will complete before we reach the end.
        • at the ev.Wait() the situation is equivalent to point 1.
      • slow tasks, i.e. tasks that haven't completed before we reach the end.
        • at the ev.Wait() the counter is not equal to 0 anymore, because of all the ev.AddCount() executed. Thus, execution will hold.
        • once all running tasks complete (and have corresponding ev.Signal() lines executed) the counter drops to 0 and execution resumes exiting the routine

Original answer

You wrote:

I am performing an operation that will create an unknown number of child operations (not tasks or threads)

So what are they? You should do something like this:

CountdownEvent ev;  
public void foo() {
    ev = new CountdownEvent(1);
    foreach ( <task in tasks_to_start> ) {
         ev.AddCount();
         // enter code here which starts your task
    }
    ev.Signal();
    ev.Wait();
}

public static void youtTask(CountdownEvent ev) {
    // some work
    // ...
    // after all is done
    ev.Signal();
}
like image 111
SOReader Avatar answered Oct 05 '22 00:10

SOReader