rage
rage

Reputation: 1837

Starting a dispatcher timer at an exact time in silverlight

I've researched how to do this in general in C# and i kept coming up with scheduling a task but, i don't know if that's what i need. This is what i've come up with

 void MainPage_Loaded(Object sender, RoutedEventArgs e)
    {
        tomorrowAt8AM = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.AddDays(1).Day, 8, 0, 0);//This is always 'tomorrow' at 8 am.. I think.
        TimeSpan timeSpan = tomorrowAt8AM.Subtract(DateTime.Now);
        timer.Interval = timeSpan; 
        timer.Tick += new EventHandler(timerTick);

        queryDB();
        timer.Start();
    }

private void timerTick(object sender, EventArgs e)
    {
        queryDB();

        //Recalculate the time interval.
        tomorrowAt8AM = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.AddDays(1).Day, 8, 0, 0);//This is always 'tomorrow' at 8 am.. I think.
        TimeSpan newTimerInterval = tomorrowAt8AM.Subtract(DateTime.Now);
        timer.Interval = newTimerInterval; 
    }

The idea is to just find out how loong it is from "now" until "tomorrow at 8am" and set that timespan as the new timer interval. In my head this works.. is there a better way to do this? Does the timer need to be restarted since i change its interval?

@Richard Deeming Here is a slice of code to test what happens in the case of Jan 31st.

 System.DateTime tomorrowAt8AM = new System.DateTime(DateTime.Now.Year, 2, 1, 8, 0, 0);//This is always the 'next' day at 8 am. 

        while (true)
        {
            DateTime temp = new DateTime(DateTime.Now.Year, 1, 31, DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second); 
            DateTime now = DateTime.Now;
            System.TimeSpan diff1 = tomorrowAt8AM.Subtract(temp);
            //Console.WriteLine(diff1.Days);
            Console.WriteLine("Days: {3}, Hours: {0}, Minutes: {1}, Seconds: {2}", diff1.Hours, diff1.Minutes, diff1.Seconds, diff1.Days);
            Thread.Sleep(1000); 
        }

When i execute this code it seems to tick down correctly..are you sure there is going to be a problem at the end of the month?

Upvotes: 0

Views: 853

Answers (1)

Richard Deeming
Richard Deeming

Reputation: 31198

Your code for "tomorrow at 8 AM" is wrong. Consider what happens on January 31st:

// DateTime.Now == 2013/01/31
// DateTime.Now.AddDays(1) == 2013/02/01
tomorrowAt8AM = new DateTime(2013, 1, 1, ...

You also need to consider what happens with daylight-saving time. When the clocks go forward, you code will execute at 9 AM. When they go back, it will execute at 7 AM. To avoid this, you should use the DateTimeOffset type:

DateTimeOffset tomorrowAt8AM = Date.Today.AddDays(1).AddHours(8);
TimeSpan interval = tomorrowAt8AM.Subtract(DateTimeOffset.Now);

The DispatcherTimer will automatically update the timer when you change the Interval property; you don't need to restart the timer.

Looking at the remarks on MSDN, the timer isn't guaranteed to fire at exactly 8 AM:

Timers are not guaranteed to execute exactly when the time interval occurs, but they are guaranteed to not execute before the time interval occurs.

You'll need to test your code to see if the timer will be accurate enough for your requirements.

Upvotes: 2

Related Questions