Return to zero CountdownEvent

.net, c#, countdownevent, multithreading

Solution

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?

- 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

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

Problem

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?

Original source