System.Threading.Timer

For the System.Threading.Timer one can do the following (Will also protect the callback-method from working on a disposed timer - ObjectDisposedException):

class TimerHelper : IDisposable
{
private System.Threading.Timer _timer;
private readonly object _threadLock = new object();

public event Action TimerEvent;

public void Start(TimeSpan timerInterval, bool triggerAtStart = false,
    object state = null)
{
    Stop();
    _timer = new System.Threading.Timer(Timer_Elapsed, state,
        System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);

    if (triggerAtStart)
    {
        _timer.Change(TimeSpan.FromTicks(0), timerInterval);
    }
    else
    {
        _timer.Change(timerInterval, timerInterval);
    }
}

public void Stop(TimeSpan timeout = TimeSpan.FromMinutes(2))
{
    // Wait for timer queue to be emptied, before we continue
    // (Timer threads should have left the callback method given)
    // - http://woowaabob.blogspot.dk/2010/05/properly-disposing-systemthreadingtimer.html
    // - http://blogs.msdn.com/b/danielvl/archive/2011/02/18/disposing-system-threading-timer.aspx
    lock (_threadLock)
    {
        if (_timer != null)
        {
            ManualResetEvent waitHandle = new ManualResetEvent(false)
            if (_timer.Dispose(waitHandle))
            {
               // Timer has not been disposed by someone else
               if (!waitHandle.WaitOne(timeout))
                  throw new TimeoutException("Timeout waiting for timer to stop");
            }
            waitHandle.Close();   // Only close if Dispose has completed succesful
            _timer = null;
        }
    }
}

public void Dispose()
{
    Stop();
    TimerEvent = null;
}

void Timer_Elapsed(object state)
{
    // Ensure that we don't have multiple timers active at the same time
    // - Also prevents ObjectDisposedException when using Timer-object
    //   inside this method
    // - Maybe consider to use _timer.Change(interval, Timeout.Infinite)
    //   (AutoReset = false)
    if (Monitor.TryEnter(_threadLock))
    {
        try
        {
            if (_timer==null)
                return;

            Action timerEvent = TimerEvent;
            if (timerEvent != null)
            {
                timerEvent(_timer, state);
            }
        }
        finally
        {
            Monitor.Exit(_threadLock);
        }
    }
}

}
This is how one can use it:

void StartTimer()
{
TimerHelper _timerHelper = new TimerHelper();
_timerHelper.TimerEvent += (timer,state) => Timer_Elapsed();
_timerHelper.Start(TimeSpan.FromSeconds(5));
System.Threading.Sleep(TimeSpan.FromSeconds(12));
_timerHelper.Stop();
}

void Timer_Elapsed()
{
// Do what you want to do
}

你可能感兴趣的:(System.Threading.Timer)