Lars Holm Jensen's Code Blog

Just another WordPress codeblog on C#, Silverlight and all things .NET

Archive for the ‘task’ tag

PostponingTimer

with one comment

This is a small timer class that I have found useful a couple of times.

It takes a job and a timeout in its Run() method, which it executes

after the timeout, unless you call the Run() method again, in which

case it postpones the execution of the job. I have mostly used this

in connection with some type of user input. For instance, doing

something when there has been a sufficient pause in scrolling or typing.

 

/// <summary>

/// This class can be used to execute a job just once after a specified

/// time since the last of a series of events has fired.

/// For instance, when implementing an Auto-Save feature in a textbox you

/// might want to avoid saving on every keypress event. In this case you can

/// call Run(() => Save(), 5000) in each keypress event. The PostPoningTimer

/// will then make sure that Save() is executed one time when 5 seconds has

/// past since the last keypress event. Any new keypresses will of course

/// repeat the process.

/// </summary>

public class PostponingTimer

{

    private Timer timer;

 

    private Dispatcher CurrentDispatcher

    {

        get

        {

#if SILVERLIGHT

            return System.Windows.Deployment.Current.Dispatcher;

#else

            return Dispatcher.CurrentDispatcher;

#endif

        }

    }

 

    private void Execute(Action job, Dispatcher dispatcher)

    {

#if SILVERLIGHT

        dispatcher.BeginInvoke(job);

#else

        dispatcher.Invoke(job);

#endif

    }

 

    /// <summary>

    /// If you keep calling Run() within timeout, job never gets executed.

    /// Only when you stop calling Run() job will run once after timeout

    /// milliseconds.

    /// <para>Job will run on calling threads dispatcher. If in silverlight

    /// the UI threads dispatcher is used.</para>

    /// </summary>

    /// <param name=”job”></param>

    /// <param name=”timeout”></param>

    public void Run(Action job, int timeout)

    {

        //Make sure the timer from last call is prevented from running.

        if (timer != null) timer.Dispose();

 

        //When not in SILVERLIGHT the line below makes sure to use the

        //dispatcher of the calling thread.

        //In silverlight the UI thread dispatcher is used.

        Dispatcher dispatcher = CurrentDispatcher;

 

        timer = new Timer(new TimerCallback((o) =>

            {

                Execute(job, dispatcher);

            }), null, timeout, Timeout.Infinite);

    }

 

    /// <summary>

    /// If you keep calling Run() within timeout, job never gets executed.

    /// Only when you stop calling Run() job will run once after timeout

    /// milliseconds.

    /// <para>Job will run on the timer’s thread.</para>

    /// </summary>

    /// <param name=”job”></param>

    /// <param name=”timeout”></param>

    public void RunNonUI(Action job, int timeout)

    {

        //Make sure the timer from last call is prevented from running.

        if (timer != null) timer.Dispose();

 

        timer = new Timer(new TimerCallback((o) =>

            {

                job();

            }), null, timeout, Timeout.Infinite);

    }

 

    /// <summary>

    /// If you keep calling Run() within timeout, job never gets executed.

    /// Only when you stop calling Run() job will run once after timeout

    /// milliseconds.

    /// <para>Actions will run on calling threads dispatcher. If in

    /// silverlight the UI threads dispatcher is used.</para>

    /// </summary>

    /// <param name=”job”></param>

    /// <param name=”timeout”></param>

    /// <param name=”callback”></param>

    public void Run(Action job, int timeout, Action callback)

    {

        //Make sure the timer from last call is prevented from running.

        if (timer != null) timer.Dispose();

 

        //When not in SILVERLIGHT the line below makes sure to use the

        //dispatcher of the calling thread.

        //In silverlight the UI thread dispatcher is used.

        Dispatcher dispatcher = CurrentDispatcher;

 

        timer = new Timer(new TimerCallback((o) =>

            {

                Execute(job + callback, dispatcher);

            }), null, timeout, Timeout.Infinite);

    }

 

    /// <summary>

    /// If you keep calling Run() within timeout, job never gets executed.

    /// Only when you stop calling Run() job will run once after timeout

    /// milliseconds.

    /// <para>Actions will run on the timer’s thread.</para>

    /// </summary>

    /// <param name=”job”></param>

    /// <param name=”timeout”></param>

    /// <param name=”callback”></param>

    public void RunNonUI(Action job, int timeout, Action callback)

    {

        //Make sure the timer from last call is prevented from running.

        if (timer != null) timer.Dispose();

 

        timer = new Timer(new TimerCallback((o) =>

            {

                (job + callback)();

            }), null, timeout, Timeout.Infinite);

    }

 

}

Written by larsholm

December 16th, 2009 at 12:55 am

Posted in .NET,Silverlight

Tagged with , , , , , , ,