Click here to Skip to main content
13,142,182 members (54,838 online)
Click here to Skip to main content
Add your own
alternative version


7 bookmarked
Posted 10 Jan 2014

Sliding Timer

, 10 Jan 2014
Rate this:
Please Sign up or sign in to vote.
How to run an action after a quiet period


This tip shows how you can schedule an action to be run after a quiet period in case you are listening to an event which is raised frequently.


I had this problem recently when developing a plugin. Our code was tracking changes in an object graph and doing some calculations based on the new state. The problem was that the event was raised in batches as the changes were cascaded through the graph. To prevent unnecessary re-calculations, we decided to wait until change propagates through the graph and all change events are fired. Only after a quiet period, the handler is invoked.

One way to do it is to use a timer and then stop and restart it each time a notification arrives. When looking at the implementation of System.Timers.Timer and System.Threading.Timer (the former uses the latter internally), I’ve got the impression that a timer is too heavyweight for this task. Also to make timer stop reliably requires further effort. But the same can be achieved simply by using a lock, a thread and Monitor class.

The Code

We create a class that will act as a timer with the ability to restart the countdown when notification arrives. Let’s assume the following declarations.

private int _timeout; // initialized in constructor
private object _lock = new Object();
private bool _isRunning = false;
public event EventHandler TimeoutElapsed;

On each change, we will call a method that will start or restart the timer respectively.

public void Ping()
    lock (_lock)
        if (_isRunning)
            _isRunning = true;

When timer is already started, pulse the lock to reset the timer. Otherwise, start a background thread that will wait until timeout expires.

private void WaitForTimeout()
    lock (_lock)
        while (Monitor.Wait(_lock, _timeout)) ;
        _isRunning = false;


The background thread waits on the lock for a specified time. If the lock is pulsed and the thread awakes before timeout has expired, it simply goes to sleep again. Otherwise if the thread is not awakened prematurely and timeout expires, it raises an event.

private void RaiseTimeoutElapsed()
    var handler = TimeoutElapsed;
    if (handler != null)
        handler(this, EventArgs.Empty);

Points of Interest

This is not reliable in the sense that there is no guarantee that the gap between events in the same logical batch will not exceed the given timeout. It’s up to you to choose proper timeout value.

If you plan to update UI in the callback, don't forget that it is fired on background thread. You need to marshal the update to the main thread.

If there is an exception thrown in the handler, it will be confined to the background thread and eventually end up in TaskScheduler.UnobservedTaskException. You may want to add some exception handling code to RaiseTimeoutElapsed() method as well.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Tomas Takac
Software Developer (Senior)
Czech Republic Czech Republic
I started programming in Basic in 1989, learned Pascal in 1993, switched to C/C++ in 1997, discovered Java in 2001 and finally settled with C#/.NET in 2003.

You may also be interested in...

Comments and Discussions

Generalit is useful Pin
Southmountain10-Jan-14 5:34
memberSouthmountain10-Jan-14 5:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170915.1 | Last Updated 10 Jan 2014
Article Copyright 2014 by Tomas Takac
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid