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