How to start a timer at a specific time for a specific time?

15,504

Solution 1

The method below starts an initial timer with an interval based on the datetime supplied (i.e. the time entered into your textbox). When the the time is reached it starts a secondary timer that will fire every four hours from that point on.

I used System.Timers Timer rather than the Sytem.Threading Timer (because ironically the system.threading timer is not thread safe!)

    public void StartTimer(DateTime time)
    {
        const int fourHoursInMilliseconds = 4 * 3600 * 1000;

        var fourHourTimer = new Timer() {Interval = fourHoursInMilliseconds};
        fourHourTimer.Elapsed += (sender, e) =>
        {
            //code to handle the elapsed event here
        };

        var span = time - DateTime.Now;
        var timer = new Timer {Interval = span.TotalMilliseconds, AutoReset = false};
        timer.Elapsed += (sender, e) => { fourHourTimer.Start();};
        timer.Start();
    }

Hope this is what you need.

Solution 2

You have 2 problems here.

  1. How to start the timer at specified time (this is called scheduling), see e.g. this.
  2. How to re-evaluate target time of possibly running timer.

Scheduling (assuming your software will be running) is basically creating timer when user finishes his input. If user changes time you have to stop that timer and start it again using new time.

Regarding re-evaluating, same tactic: create and start new timer every time user change value, taking in account whenever timer is running and already passed time.

So basically it will be 2 timers, where one is used to start another.

Pseudocode:

 DispatcherTimer _scheduler;
 DispatcherTimer _timer;
 DateTime _start;
 TimeSpan _duration;

 // call this when specified time is changed
 void Schedule(DateTime time)
 {
     _start = time;
     // prevent any logic to run if timer is counting duration
     if(_timer != null)
         return;
     // stop scheduler
     if(_scheduler != null)
         _scheduler.Stop();
     // create new scheduler
     _scheduler = new DispatcherTimer { Interval = _start - DateTime.Now };
     _scheduler.Tick = (s, e) =>
     {
         Start(_duration); // here scheduler will start timer
         _scheduler.Stop(); // after that you don't need scheduler anymore
         _scheduler = null;
     }
     _scheduler.Start();
 }

 // call this when duration is changed
 void Start(TimeSpan duration)
 {
     _duration = duration;
     // prevent from running before starting time
     if(DateTime.Now < _start)
         return;
     // stop running timer
     if(_timer != null)
         _timer.Stop();
     // create timer to count duration including already expired time
     _timer = new DispatcherTimer { Interval = _duration - (DateTime.Now - _start) };
     _timer.Tick = (s, e) =>
     {
         ... // whatever
         _timer.Stop(); // clean up
         _timer = null;
     }
     _timer.Start();
 }

I am using DispatcherTimer to avoid invoke when starting another DispatcherTimer. Both Schedule() and Start() should be called from UI thread (e.g. TextChanged event handler).

Share:
15,504

Related videos on Youtube

thecodrr
Author by

thecodrr

The story about me goes like this: once upon a time there was a kid who was very young, he had an inherent passion for computer but he never had one. Watching other people play games, write articles and edit pictures in Paint fascinated him immensely. Several years later when he was mature enough to afford a computer, he transformed his passion into programming and building apps. The first programming language he learned was C++ but he never got to use to very much as he shifted very quickly to C#. For 5 years he was satisfied until he was introduced into the world of Android and React Native. He changed ship and became a React Native developer. He got so excited developing cool and amazing apps that his excitement led him to contribute in React Native and React Native CLI repos. The story goes on and his life goes on. Aside from coding, he likes to design stuff like logos and animations, read fantastical books and hike the boots out of the mountains! Disclaimer: His story is his alone. :D

Updated on June 25, 2022

Comments

  • thecodrr
    thecodrr almost 2 years

    Here is the scenario:

    There is a Textbox in which a user enters the time at which the DispatcherTimer must start. The Timer is set to run for 4 hours always and Timer.Tick event plays a sound. Let's say the timer starts at 04:00:00 (HH:mm:ss), it should run till 8:00:00 and then stop. Then when the user changes the time, let's say, to 09:00:00. The timer should run till 13:00:00 and so on.

    How can this be achieved? I can't run a 1 minute timer that keeps checking for the right time because that will be very heavy on the system.

    All help is appreciated. Thank you in advance.

    • Alex
      Alex almost 8 years
      I wouldn't say 1 minute timer is a performance issue for any modern computer but I would use Windows Tasks for this sort of scenario
  • thecodrr
    thecodrr almost 8 years
    This was exactly what I needed. It is short and precise. Thank you.

Related