How to run code daily at specific time in C# Part 2


dailyruncode

Few months ago I wrote blog post about how to run code daily at specific time. I dint know that the post will be the most viewed post on my blog. Also there were several questions how to implement complete example. So today I have decided to write another post, and extend my previous post in order to answer thise question as well as to generalize this subject in to cool demo called Scheduler DEMO.

The post is presenting simple Windows Forms application which calls a method for every minute, day, week, month or year. Also demo shows how to cancel the scheduler at any time.

The picture above shows simple Windows Forms application with two  numeric control which you can set starting hour and minute for the scheduler. Next there is a button Start to activate timer for running code, as well as Cancel button to cancel the scheduler. When the time is come application writes the message on the Scheduler Log.

Implementation of the scheduler

Scheduler is started by clicking the Start button which is implemented with the following code:

/// <summary>
/// Setting up time for running the code
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void startBtn_Click(object sender, EventArgs e)
{

    //retrieve hour and minute from the form
    int hour = (int)numHours.Value;
    int minutes = (int)numMins.Value;

    //create next date which we need in order to run the code
    var dateNow = DateTime.Now;
    var date = new DateTime(dateNow.Year, dateNow.Month, dateNow.Day, hour, minutes, 0);

    listBox1.Items.Add("**********Scheduler has been started!*****");

    //get nex date the code need to run
    var nextDateValue=getNextDate(date,getScheduler());

    runCodeAt(nextDateValue, getScheduler());

}

When the time is defined then the runCodeAt method is called which implementation can be like the following;

/// <summary>
/// Determine the timeSpan Dalay must wait before run the code
/// </summary>
/// <param name="date"></param>
/// <param name="scheduler"></param>
private void runCodeAt(DateTime date,Scheduler scheduler )
{
    m_ctSource = new CancellationTokenSource();

    var dateNow = DateTime.Now;
    TimeSpan ts;
    if (date > dateNow)
        ts = date - dateNow;
    else
    {
        date = getNextDate(date, scheduler);
        ts = date - dateNow;
    }

    //enable the progressbar
    prepareControlForStart();

    //waits certan time and run the code, in meantime you can cancel the task at anty time
    Task.Delay(ts).ContinueWith((x) =>
        {
            //run the code at the time
                methodToCall(date);

                //setup call next day
                runCodeAt(getNextDate(date, scheduler), scheduler);

        },m_ctSource.Token);
}

The method above creates the cancelationToken needed for cancel the scheduler, calculate timeSpan – total waiting time, then when the time is come call the method methodToCall and calculate the next time for running the scheduler.

This demo also shows how to wait certain amount of time without blocking the UI thread.

The full demo code can be found on OneDrive.

About Bahrudin Hrnjica

PhD in Mechanical Engineering, Microsoft MVP for .NET. Likes .NET, Math, Mechanical Engineering, Evolutionary Algorithms, Blogging.

Posted on 13/10/2014, in .NET, C#, CodeProject, Programiranje and tagged , , , , , . Bookmark the permalink. 10 Comments.

  1. Sir, can I use this DelayDemoForms of yours? It’ll be much appreciated for the use of our projects. Will wait for your response and permission before we officially use it. Thanks.

    • Hi,

      thanks for interesting in my projects. Of course you can use it,please notes that all stuff here is under creative common license, that means you can use it regardless of usage type: commercial or testing with proper citations.

  2. Okay thanks sir, proper citations will be done. I kinda having this error in Task.Delay. It says that does not contain a definition for ‘Delay’ under the System.Threading.Tasks. Do you know how to solve this issue, sir? I’ve tried other namespaces and still nothing works. Hope you can help me with this one sir, thanks.

  3. vikas tyagi

    Tello,
    Thanks for the article.
    i am using your code in a web application for sending email on daily bases but it is not working.
    when i am using the same code for every minutes it is working fine but for a day it is not sending any email to me.
    please help me
    here is my code that i am using

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Threading;
    using System.Threading.Tasks;

    namespace EmailApplication
    {
    enum Scheduler
    {
    EveryMinutes,
    EveryHour,
    EveryHalfDay,
    EveryDay,
    EveryWeek,
    EveryMonth,
    EveryYear,
    }
    public class EmailScheduler
    {
    CancellationTokenSource m_ctSource;
    public void Start()
    {
    int hour = DateTime.Now.Hour;
    int minutes = DateTime.Now.Minute;
    var dateNow = DateTime.Now;
    var date = new DateTime(dateNow.Year, dateNow.Month, dateNow.Day, hour, minutes, 0);
    var nextDateValue = getNextDate(date, getScheduler());
    runCodeAt(nextDateValue, getScheduler());

    }

    private void runCodeAt(DateTime date, Scheduler scheduler)
    {
    m_ctSource = new CancellationTokenSource();

    var dateNow = DateTime.Now;
    TimeSpan ts;
    if (date > dateNow)
    ts = date – dateNow;
    else
    {
    date = getNextDate(date, scheduler);
    ts = date – dateNow;
    }
    //waits certan time and run the code, in meantime you can cancel the task at anty time
    Task task = Delay(ts.TotalMilliseconds);
    task.ContinueWith((x) =>
    {
    //run the code at the time
    methodToCall(date);

    //setup call next day
    runCodeAt(getNextDate(date, scheduler), scheduler);
    }, m_ctSource.Token);
    }
    Task Delay(double milliseconds1) // Asynchronous NON-BLOCKING method
    {
    int milliseconds = (int)milliseconds1;
    var tcs = new TaskCompletionSource();
    new Timer(_ => tcs.SetResult(null)).Change(milliseconds, -1);
    return tcs.Task;
    }

    private DateTime getNextDate(DateTime date, Scheduler scheduler)
    {
    switch (scheduler)
    {
    case Scheduler.EveryMinutes:
    return date.AddMinutes(1);
    case Scheduler.EveryHour:
    return date.AddHours(1);
    case Scheduler.EveryHalfDay:
    return date.AddHours(12);
    case Scheduler.EveryDay:
    return date.AddDays(1);
    case Scheduler.EveryWeek:
    return date.AddDays(7);
    case Scheduler.EveryMonth:
    return date.AddMonths(1);
    case Scheduler.EveryYear:
    return date.AddYears(1);
    default:
    throw new Exception(“Invalid scheduler”);
    }

    }

    private void methodToCall(DateTime time)
    {
    //setup next call
    var nextTimeToCall = getNextDate(time, getScheduler());

    Email.SendEmail();
    }

    private Scheduler getScheduler()
    {
    return Scheduler.EveryDay;
    }
    }
    }

    Thanks in advance.

    Vikas Tyagi.

    • Hi
      I think it is not about the code, it is about the web site I guess. Because the code must be in some kind of service which is continuously working, but the website cannot do that by default.
      Thats all I can help

      Bahrudin

      • vikas tyagi

        hello,

        Thanks for your reply.
        we are using this code in a web application hosted on IIS and calls the Start() method once will it work for the specified time interval.
        means for one day if i hosted the web site on IIS.

        Thanks

  4. Hello Bahrudin Hrnjica,
    Thanks you so much for your sample code. Current i’m developing an app maybe start action at 3 point time/ day. It’s really helpful with my application.

  5. Hi, Sir…

    I just want to thank you for sharing your app, it’s simply great, and it helps me a lot to build a program that helps me to update the state of some stuff in my work.

    Keep being this great, and have anice day…

  6. Alberto Rojas

    hello … I would like to know if there is any way my form is run automatically at a specified time without the user runs.

  1. Pingback: How to run code daily at specific time in C# | Bahrudin Hrnjica Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s