Hello Guys, Today I’m going to create a very simple Task Scheduler using c# without using any Library. Using this Task Scheduler we’ll be able to Schedule a Task by Seconds, Minutes, Hours and Days. 

 A Few Days ago, I was working on one of my projects & met with a challenge where I needed to run a task every 30 minutes and another task daily at 2 am. After searching a bit I found answers about Quartz.net. But it seems to be too big for my project. I want an equivalent but the simpler solution for my Project. So I decided to create my own Task Scheduler. 

In this article, I’m going to show you how you can create a very Simple Task Scheduler using very clean code. 

Let’s start by creating a console project.

Follow the best practice & create a new folder with the name as “Services” & inside this Folder create a new File as “SchedulerService.cs”

Now paste this code in the newly created File.

using System;
using System.Collections.Generic;
using System.Threading;

public class SchedulerService
{
    private static SchedulerService _instance;
    private List<Timer> timers = new List<Timer>();

    private SchedulerService() { }

    public static SchedulerService Instance => _instance ?? (_instance = new SchedulerService());

    public void ScheduleTask(int hour, int min, double intervalInHour, Action task)
    {
        DateTime now = DateTime.Now;
        DateTime firstRun = new DateTime(now.Year, now.Month, now.Day, hour, min, 0, 0);
        if (now > firstRun)
        {
            firstRun = firstRun.AddDays(1);
        }

        TimeSpan timeToGo = firstRun - now;
        if (timeToGo <= TimeSpan.Zero)
        {
            timeToGo = TimeSpan.Zero;
        }

        var timer = new Timer(x =>
        {
            task.Invoke();
        }, null, timeToGo, TimeSpan.FromHours(intervalInHour));

        timers.Add(timer);
    }
}

Now create another File inside your root directory as “MyScheduler.cs” and paste this code 

using System;

public static class MyScheduler
{
    public static void IntervalInSeconds(int hour, int sec, double interval, Action task)
    {
        interval = interval/3600;
        SchedulerService.Instance.ScheduleTask(hour, sec, interval, task);
    }

    public static void IntervalInMinutes(int hour, int min, double interval, Action task)
    {
        interval = interval/60;
        SchedulerService.Instance.ScheduleTask(hour, min, interval, task);
    }

    public static void IntervalInHours(int hour, int min, double interval, Action task)
    {
        SchedulerService.Instance.ScheduleTask(hour, min, interval, task);
    }

    public static void IntervalInDays(int hour, int min, double interval, Action task)
    {
        interval = interval * 24;
        SchedulerService.Instance.ScheduleTask(hour, min, interval, task);
    }
}

Now you have your project structure something like this.

 Task Scheduler project

Now It’s time to use the scheduler from your “Program.cs”

Running a Scheduler is very simple you have four methods => “IntervalInSeconds”, “IntervalInMinutes”, “IntervalInHours” & “IntervalInDays”, you just need to call one of these methods & pass the first 2 parameters as starting hour & minutes. If specified start time has over scheduling start on the next day at that time.

So here’s the Code for “Program.cs”

using System;

namespace TaskScheduler
{
    class Program
    {
        static void Main(string[] args)
        {
            // For Interval in Seconds 
            // This Scheduler will start at 11:10 and call after every 15 Seconds
            // IntervalInSeconds(start_hour, start_minute, seconds)
            MyScheduler.IntervalInSeconds(11, 10, 15,
            () => {

                Console.WriteLine("//here write the code that you want to schedule");
            });

            // For Interval in Minutes 
            // This Scheduler will start at 22:00 and call after every 30 Minutes
            // IntervalInSeconds(start_hour, start_minute, minutes)
            MyScheduler.IntervalInMinutes(22, 00, 30,
            () => {

                Console.WriteLine("//here write the code that you want to schedule");
            });

            // For Interval in Hours 
            // This Scheduler will start at 9:44 and call after every 1 Hour
            // IntervalInSeconds(start_hour, start_minute, hours)
            MyScheduler.IntervalInHours(9, 44, 1,
            () => {

                Console.WriteLine("//here write the code that you want to schedule");
            });

            // For Interval in Seconds 
            // This Scheduler will start at 17:22 and call after every 3 Days
            // IntervalInSeconds(start_hour, start_minute, days)
            MyScheduler.IntervalInDays(17, 22, 3,
            () => {

                Console.WriteLine("//here write the code that you want to schedule");
            });

            Console.ReadLine();
        }
    }
}

Comment If you find any problem. You can also download complete code for this Scheduler from Github.

Download Complete Code

Limitations

One of our Community member Umar Tarar found a very valid point…

Using System.Threading.Timer has a limitation on its ‘period’ param i.e, the maximum interval that you can set for the timer is 49 days 17 hours 2 min 47 sec and 294 ms, this is because the max value that can be passed as period (or interval) is the max number that a uint can hold and that is UInt32.MaxValue = 4294967294 in milliseconds. This is because the internal implementation of this timer can accept the interval as uint only even though the wrapper Timer constructor accepts it int, long, Timespan etc.
This limitation is mentioned in the official documentation: Here

Here are more Articles you might be Interested

– Creating Admin Panel in Asp.net Core MVC – Step by Step Tutorial

Generate QR Code Using ASP.NET CORE 

– Dynamic Role-Based Authorization Asp.net Core

– Upload File to SFTP Server using C#

 

Author

I'm passionate about learning new technologies as well as mentoring and helping others get started with their programming career. This blog is my way of giving back to the Community.

12 Comments

  1. Hi Shehryar Khan,
    Thanks alot for your effort but it is not working with me , Could you Please help me?

  2. Hello,
    Thanks for your article and project, it has helped me a lot.
    However I am having problems using it. When the program is still running, how do I stop or kill this scheduler?
    I have tried using a clear timers by an function, but there are times when the program cannot stop.
    Many tks!

  3. If you adjust the time during program startup
    for example…
    If the program is run on February 24, 2019 and another user changes to 2020, the scheduler will not work again. How do I fix it?

  4. thx for code!!

    I have a question.
    Does this code run only in .net core?
    It did not work on the console.

  5. if we are running this on local machine this will work fine. But what i we are going to deploy it on live server. Here you have used console.readline() in last line of your program means visual studio should keep running in order to fire those scheduled task?.

    • Yes, It needs to keep running. But you don’t need to run Visual Studio on your server. Just Publish your .exe & run it on your server.

  6. Nice work. But why not just use the Task Scheduler that comes built into Windows? It has the benefits of being feature-rich and tested by Microsoft.

    • Yes, I second that unless there is a need to port this code to non windows. But in all the senses, it’s a great article. I also would say, you can explore the lib of windows task scheduler also, now with core, it may have possibilities of shipping the lib along.

  7. Dear Shehryar,

    Using System.Threading.Timer has a limitation on its ‘period’ param i.e, the maximum interval that you can set for the timer is 49 days 17 hours 2 min 47 sec and 294 ms, this is because the max value that can be passed into as period (or interval) is the max number that a uint can hold and that is UInt32.MaxValue = 4294967294 in milliseconds. This is because the internal implementation of this timer can accept the interval as uint only even though the wrapper Timer constructor accept it int, long, Timespan etc.
    This limitation is mentioned in the official documentation: https://docs.microsoft.com/en-us/dotnet/api/system.threading.timer.change?redirectedfrom=MSDN&view=netframework-4.7.2#System_Threading_Timer_Change_System_TimeSpan_System_TimeSpan_

Write A Comment