The .NET4 Countdown Synchronization Primitive

Download this episode

Download Video


Join Josh and Steve as they demonstrate how to use the new .NET4 Countdown event synchronization primitive in task coordination scenarios.

Countdown and related constructs are new with .NET4 and Visual Studio 2010.

Learn more about the System.Collections.Concurrent namespace and keep abreast of Parallel Computing tools and techniques via the Concurrency Dev Center.

See all videos in this series.



Available formats for this video:

Actual format may change based on video formats available and browser capability.

    The Discussion

    • User profile image

      It seems to me that in order to have a race condition ce.AddCount() should be inside lambda in the last code sample.

      As long as ce.AddCount() is inside foreach loop on the main thread there won't be any race conditions, so adding "one for the host" before and then taking it out after the loop is kind of pointless.


      Also, guys, _No Sound_ in SL3 on XP SP3 _again_.





    • User profile image

      Good job! Thanks. I can't wait.

    • User profile image

      Seva, the problem is that the work item could complete asynchronously before the next item is even created on the main thread.  The main thread could add 1 count, kick off a work item, and that work item could complete and decrement the count prior to the main thread looping back around and adding to the count again.  That would cause the event to reach 0 even though additional work remained.

    • User profile image

      Are you saying Wait is triggered if the internal count is EVER zero? Such as the first lambda completing before the second time the main thread runs through the for loop?


      If it triggers only if the count is currently zero, there shouldn't be a race becuase at the Wait the main thread has already added 1 for every element to be processed.


    • User profile image

      Yes... once zero, the event is set, such that anyone waiting on it will wake up.  And unless you call Reset on the event, once zero, attempting to increase the count will result in an exception.  This design actually helps to minimize races between threads changing the count (up or down) and threads waiting on the event.

    • User profile image

      Ah, "Once zero it cannot be incremented" - that's what was missing. Then it's all cool and dandy Smiley

      I guess that the counter is NULL originally (if not set to any positive integer).

    • User profile image

      The whole "Don't forget to add one" is simply a hack.  Threaded programming is hard, and this tool keeps it that way, it's just not up to the task.


      It would be much better if this primitive was not added at all than released in this form.

    • User profile image

      Yeah, that's a hack and is a bad one too. Why not to make "done adding" semantics explicit at least?

      Then instead of add one before, remove one after there will be explicit call to ce.NoMoreCounterIncrements()

      It doesn't guarantee that programmer won't forget to add it into the code, but that's one change to one code line as opposed to two (and it's a better "pattern" than the alternative).


      Plus, if this primitive constructor accepted nested lambdas, then AddCounter() and NoMoreCounterIncrements() could be hidden from the programmer all together. Just declare what you want to spawn and how many of those in a nested lambda and happily wait for completion.

    • User profile image

      Agreed with sokhaty.  As it stands, how exactly is this different from a counting semaphore?

    • User profile image

      re: "how exactly is this different from a counting semaphore?"


      In a sense, it's almost the opposite.  With a semaphore, you block while the count is zero; with a countdown event, you block until it's zero.

    • User profile image

      re: "The whole "Don't forget to add one" is simply a hack"


      Thanks for the feedback.   I understand that viewpoint, though I personally don't view this as a hack at all.  CountdownEvent is used to keep track of a number of outstanding work items, and there's nothing at all that says one of those items can't be on the current thread, nor is there any reason all of the operations need to be homogenous in workload.  In this example, one of the work items is the work of spinning off all other work items; since we know about that piece of work when we start, we initialize the CountdownEvent to 1, and when we're done with that piece of work, as with all other pieces of work tracked by the event, we signal.

    • User profile image

      As I see it, a counting semaphore is a form of throttle. This primitive is not related.


      For me, the example code scenario is very familiar and this replaces the array of wait handles that I usually have to maintain when spinning up work items. I must admit to frowning at the 'hack' as it looked easy to forget, and like an after thought. There could be something like a FinishedAdding() method (just sets an initial handle) just to emphasise the requirement, or maybe not.

    Comments closed

    Comments have been closed since this content was published more than 30 days ago, but if you'd like to send us feedback you can Contact Us.