//-------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: ActionCountdownEvent.cs // //-------------------------------------------------------------------------- namespace System.Threading { /// Runs an action when the CountdownEvent reaches zero. public class ActionCountdownEvent : IDisposable { private readonly CountdownEvent _event; private readonly Action _action; private readonly ExecutionContext _context; /// Initializes the ActionCountdownEvent. /// The number of signals required to set the CountdownEvent. /// The delegate to be invoked when the count reaches zero. public ActionCountdownEvent(int initialCount, Action action) { // Validate arguments if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount"); if (action == null) throw new ArgumentNullException("action"); // Store the action and create the event from the initial count. If the initial count forces the // event to be set, run the action immediately. Otherwise, capture the current execution context // so we can run the action in the right context later on. _action = action; _event = new CountdownEvent(initialCount); if (initialCount == 0) action(); else _context = ExecutionContext.Capture(); } /// Increments the current count by one. public void AddCount() { // Just delegate to the underlying event _event.AddCount(); } /// Registers a signal with the event, decrementing its count. public void Signal() { // If signaling the event causes it to become set if (_event.Signal()) { // Execute the action. If we were able to capture a context // at instantiation time, use that context to execute the action. // Otherwise, just run the action. if (_context != null) { ExecutionContext.Run(_context, _ => _action(), null); } else _action(); } } /// Releases all resources used by the current instance. public void Dispose() { Dispose(true); } /// Releases all resources used by the current instance. /// /// true if called because the object is being disposed; otherwise, false. /// protected void Dispose(bool disposing) { if (disposing) _event.Dispose(); } } }