1

I have a .Net Core 6 project and I want do schedule some task working at every day 09:00 am.

What is the best way for task scheduler?

Note: Hangfire is good solution but it is working with DataBase, this is bad for my project.

Fehmi Aksakal
  • 31
  • 1
  • 7
  • 2
    Does this answer your question? [What is the equivalent to cron jobs in ASP.NET?](https://stackoverflow.com/questions/8226986/what-is-the-equivalent-to-cron-jobs-in-asp-net) – Artur May 25 '22 at 07:26
  • 3
    For local scheduling Quartz is a mainstream choice in .net world – OrcusZ May 25 '22 at 07:37
  • Artur, OrcusZ thanks for your comments. I Will integrated the Quartz to my project. – Fehmi Aksakal May 25 '22 at 08:13
  • 1
    You can look into HangFire. It is very nice and easy to integrate. The docs are a bit outdated, but they do the job. – AchoVasilev May 25 '22 at 15:59

2 Answers2

1

You can work with timers.

static DateTime GetNextRunTime()
{
    DateTime now = DateTime.Now;
    if (now.Hour < 9)
    {
        // If time of the day is before 9:00 am, then job will run today at 9
        // Using this way instead of DateTime.Today.AddHours(9) because it can cause weird issues with Daylight Saving when time offset changes
        return new DateTime(now.Year, now.Month, now.Day, 9, 0, 0);
    }
    // Job will run tommorow at 9:00
    DateTime tomorrow = DateTime.Today.AddDays(1);
    return new DateTime(tomorrow .Year, tomorrow .Month, tomorrow .Day, 9, 0, 0);
}

static void ScheduleNextJob(Action action)
{
    var dueTime = GetNextRunTime() - DateTime.Now;
    
    System.Threading.Timer timer = null;
    timer = new Timer(() => 
    {
        // run your code
        try
        {
             action();
        }
        catch
        {
              // Handle the exception here, but make sure next job is scheduled if an exception is thrown by your code.
        }
        ScheduleNextJob(action); // Schedule next job
        timer?.Dispose(); // Dispose the timer for the current job
    }, null, dueTime, TimeSpan.Infinite);
}

The reason for creating a new timer everytime we schedule a job rather than have a timer with 24 hours period is again Daylight saving. On days the time changes from summer to winter or vice versa, the difference between 9am and 9am next day is not 24 hours.

Sherif Elmetainy
  • 4,034
  • 1
  • 13
  • 22
  • Hi, thanks your answer. I think your solution is bad for than more tasks. Your code maybe good for one or two scheduler job, but not good for a lot of schedule jobs. Thanks again. – Fehmi Aksakal May 25 '22 at 08:17
  • Timers are not reliable because they are not persisted. For example, a new deployment causes an app to restart so you have to write all kinds of logic to mitigate that. Better use a well tested lib for that. – Peter Bons May 25 '22 at 08:25
  • 2
    @PeterBons, yeah I know that timers are not persisted. But the question said "no database", so I thought the poster didn't want persistence. For a single task with a simple schedule (like in the question) where the app can schedule it at startup, the timer solution adds two function to the entire project and is easy to test. Of course I 100% agree that for more complex scheduling scenarios, a library like Quartz is much better. – Sherif Elmetainy May 25 '22 at 08:52
  • You shouldn't have to utilize a bloated 3rd party lib (Quartz) for something so rudimentary. This is the correct solution. Thank you @SherifElmetainy – Mark Entingh Apr 16 '23 at 14:52
1

NET 6 has built in support for recurring tasks and you can build a windows service pretty easily. Building this as a windows service means that once you've installed it you don't have to worry about a reboot because you can tell the service to start on reboot.

Checkout Create a Windows Service using BackgroundService

and Worker Services in .NET

Your total reading time would be about 20 minutes, so it is pretty straight forward. It is a bit too involved to explain fully in a Stack Overflow answer.

GlennSills
  • 3,977
  • 26
  • 28