Adi
Adi

Reputation: 1455

How to set timer to execute at specific time in c#

I have a requirement where i need to execute timer at 00:01:00 A.M every day...But i am not getting how to achieve this ..If i am taking Systems time,it can be in different format.. Here is my timer code..

static System.Timers.Timer timer;
timer = new System.Timers.Timer();
timer.Interval = 1000 * 60 * 60 * 24;//set interval of one day
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
start_timer(); 

static void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        // Add timer code here

    }
    private static void start_timer()
    {
        timer.Start();
    }

Upvotes: 19

Views: 52218

Answers (5)

user3856874
user3856874

Reputation: 1

I used this way, only for a fixed time at 6 am:

private void TimerReset()
{
    DateTime datetoday = DateTime.Now;
    DateTime datetomorrow = datetoday.AddDays(1);
    int nmonth = datetomorrow.Month;
    int nyear = datetomorrow.Year;
    int nday = datetomorrow.Day;
    
    DateTime datetomorrow1 = new DateTime(nyear, nmonth, nday, 06, 00, 00);
    TimeSpan difference = (datetomorrow1 - datetoday );

    timer1.Interval = (int) difference.TotalMilliseconds;
    timer1.Enabled = true ;
}

private void timer1_Tick(object sender, EventArgs e)
{
    timer1.Enabled = false ;

    // code to execute
    
   // reload the timer
   TimerReset();
           
   timer1.Enabled = true;
}

Upvotes: 0

Nico
Nico

Reputation: 12683

If you want to start a timer at exactly 00:01:00am do some processing time and then restart the timer you just need to calculate the difference between Now and the next 00:01:00am time slot such as.

static Timer timer;
static void Main(string[] args)
{
    setup_Timer();
}

static void setup_Timer()
{
    DateTime nowTime = DateTime.Now;
    DateTime specificTime = new DateTime(nowTime.Year, nowTime.Month, nowTime.Day, 1, 0, 0, 0);
    if (nowTime > specificTime)
        specificTime= specificTime.AddDays(1);

    double tickTime = (specificTime- nowTime).TotalMilliseconds;
    timer = new Timer(tickTime);
    timer.Elapsed += timer_Elapsed;
    timer.Start();
}

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    timer.Stop();
    //process code..
    setup_Timer();
}

Upvotes: 35

Miraj Mohamed
Miraj Mohamed

Reputation: 11

Here is a timer implementation which takes an Interval (just like any other timer) and fires exactly when that interval expires, even the machine goes to sleep mode in between.

public delegate void TimerCallbackDelegate(object sender, ElapsedEventArgs e);
public class TimerAbsolute : System.Timers.Timer
{
    private DateTime m_dueTime;
    private TimerCallbackDelegate callback;

    public TimerAbsolute(TimerCallbackDelegate cb) : base()
    {
        if (cb == null)
        {
            throw new Exception("Call back is NULL");
        }
        callback = cb;
        this.Elapsed += this.ElapsedAction;
        this.AutoReset = true;
    }

    protected new void Dispose()
    {
        this.Elapsed -= this.ElapsedAction;
        base.Dispose();
    }

    public double TimeLeft
    {
        get
        {
            return (this.m_dueTime - DateTime.Now).TotalMilliseconds;
        }
    }

    public int TimeLeftSeconds
    {
        get
        {
            return (int)(this.m_dueTime - DateTime.Now).TotalSeconds;
        }
    }


    public void Start(double interval)
    {
        if (interval < 10)
        {
            throw new Exception($"Interval ({interval}) is too small");
        }

        DateTime dueTime = DateTime.Now.AddMilliseconds(interval);

        if (dueTime <= DateTime.Now)
        {
            throw new Exception($"Due time ({dueTime}) should be in future. Interval ({interval})");
        }
        this.m_dueTime = dueTime;

        // Timer tick is 1 second
        this.Interval = 1 * 1000;
        base.Start();
    }

    private void ElapsedAction(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (DateTime.Now >= m_dueTime)
        {
            // This means Timer expired
            callback(sender, e);
            base.Stop();
        }
    }
}

Upvotes: 1

Grant Winney
Grant Winney

Reputation: 66439

What you should do is write your program that does whatever you need it to do, and then use your OS's built-in task scheduler to fire it off. That'd be the most reliable. Windows's Task Scheduler, for instance, can start your app before the user logs in, handle restarting the app if necessary, log errors and send notifications, etc.

Otherwise, you'll have to run your app 24/7, and have it poll for the time at regular intervals.

For instance, you could change the interval every minute:

timer.Interval = 1000 * 60;

And inside your Elapsed event, check the current time:

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    if (DateTime.Now.Hour == 1 && DateTime.Now.Minute == 0)
    {
        // do whatever
    }
}

But this is really unreliable. Your app may crash. And dealing with DateTime's can be tricky.

Upvotes: 12

itsme86
itsme86

Reputation: 19486

You could always calculate it:

static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    // Do stuff

    start_timer();
}

private static void start_timer()
{
    timer.Interval = CalculateInterval();
    timer.Start();
}

private static double CalculateInterval()
{
    // 1 AM the next day
    return (DateTime.Now.AddDays(1).Date.AddHours(1) - DateTime.Now).TotalMilliseconds;
}

Upvotes: 2

Related Questions