.NET, event every minute (on the minute). Is a timer the best option?

Viewed 78820

I want to do stuff every minute on the minute (by the clock) in a windows forms app using c#. I'm just wondering whats the best way to go about it ?

I could use a timer and set its interval to 60000, but to get it to run on the minute, I would have to enable it on the minute precisely, not really viable.

I could use a timer and set its interval to 1000. Then within its tick event, I could check the clocks current minute against a variable that I set, if the minute has changed then run my code. This worries me because I am making my computer do a check every 1 second in order to carry out work every 1 minutes. Surely this is ugly ?

I'm using windows forms and .Net 2.0 so do not want to use the DispatchTimer that comes with .Net 3.5

This must be a fairly common problem. Have any of you a better way to do this?

15 Answers

Building on the answer from aquinas which can drift and which doesn't tick exactly on the minute just within one second of the minute:

static System.Timers.Timer t;

static void Main(string[] args)
{
    t = new System.Timers.Timer();
    t.AutoReset = false;
    t.Elapsed += new System.Timers.ElapsedEventHandler(t_Elapsed);
    t.Interval = GetInterval();
    t.Start();
    Console.ReadLine();
}

static double GetInterval()
{
    DateTime now = DateTime.Now;
    return ((60 - now.Second) * 1000 - now.Millisecond);
}

static void t_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    Console.WriteLine(DateTime.Now.ToString("o"));
    t.Interval = GetInterval();
    t.Start();
}

On my box this code ticks consistently within .02s of each minute:

2010-01-15T16:42:00.0040001-05:00
2010-01-15T16:43:00.0014318-05:00
2010-01-15T16:44:00.0128643-05:00
2010-01-15T16:45:00.0132961-05:00

I have a solution based on Environment.TickCount

    static void Main(string[] args)
    {
        //constatnt total miliseconds to one minute
        const Int32 minuteMilisecond = 60 * 1000;

        //get actual datetime
        DateTime actualDateTime = DateTime.UtcNow;

        //compenzation to one minute
        Int32 nexTimer = Environment.TickCount + ((59 - actualDateTime.Second) * 1000) + (999 - actualDateTime.Millisecond);

        //random fuction to simulate different delays on thread
        Random rnd = new Random();

        //main loop
        while (true) 
        {
            if (Environment.TickCount > nexTimer)
            {
                nexTimer += minuteMilisecond;

                //execute your code here every minute
                Console.WriteLine($"actual DateTime: {DateTime.Now.ToString("yyyy.MM.dd HH:mm:ss:ffff")}");
            }

            //random sleep between 100 - 200 ms
            Thread.Sleep(rnd.Next(100, 200));
        }
    }
Related