JPatrik
JPatrik

Reputation: 23

C# Task run only if time is right - at a certain time

Okay, so i need to build a c# task that will only run at a certian time, the time will come from a SQL database, and it can be more then 1 time a day.

For an example, the c# task need to run at 6:00, 13:00, 15:00 and 19:00. and at the meanwhile time it will sleep.

I was thinking to just do Task.delay(60000) and check then run on a loop of times and check if DateTime.Now < time.

But that seems like it will overload my computer wouldn't it? I cant use windows manager because my task is on a windows service doing other tasks.

What is the best possible way of doing this such of work?

P.S : the task job is to go for an api and get info into a Database.

Thanks a lot for helping!

Upvotes: 1

Views: 3503

Answers (2)

kkirk
kkirk

Reputation: 367

You should take a look at Quartz .NET:

https://www.quartz-scheduler.net/

If I understand you correctly, the times when it needs to run will be fetched from a SQL database, so your windows service should probably check every once in a while, whether the schedule has been updated and re-schedule in the application if relevant.

Another project which is really nice is Hangfire:

https://www.hangfire.io/

Either one would probably allow you to do what you need.

Here's an example of what you could do (in Hangfire):

// Get database times. For simplicity I'll assume that you
// just get a list of dates. Assume they're stored in in UTC
List<DateTime> times = this.database.GetSchedule();

// Loop the times and schedule jobs
foreach(var time in times) 
{
   var timeUntilJob = time - DateTime.UtcNow;
   var jobId = BackgroundJob.Enqueue(() => YourMethodToDoWork(), timeUntilJob);

   // You will need to somehow store the job ids, in case you want to 
   // cancel an execution scheduled for a later time (e.g. if you
   // need to update it if the database-stored schedule changes).
   // You could then invoke BackgroundJob.Delete(jobId)
 }

Hangfire can e.g. store the scheduled invocations in a SQL Server database (or Redis or MongoDb, etc). It creates records containing the assembly, the method and the arguments to invoke at the scheduled time. This means that even if your service breaks down, you won't lose executions of your task.

You could just create a timer that ticks every X hours and deletes the current schedule, and updates with the current values in the database. But how you want to do that is of course up to your specific case.

Upvotes: 2

Antoine V
Antoine V

Reputation: 7204

You can use Task scheduler Windows

The Task Scheduler can be used to execute tasks such as starting an application, sending an email message, or showing a message box. Tasks can be scheduled to execute:

At a specific time.

At a specific time on a daily schedule.

You can try this to create a task dynamically for each day,

   using System;
   using Microsoft.Win32.TaskScheduler;
   static void Main(string[] args)
   {
      // Get the service on the local machine
      using (TaskService ts = new TaskService())
      {
         // Create a new task definition and assign properties
         TaskDefinition td = ts.NewTask();
         td.RegistrationInfo.Description = "Does something";

         // Create a trigger that will fire the task at this time every other day
         td.Triggers.Add(new DailyTrigger { DaysInterval = 2 });

         // Create an action that will launch your application whenever the trigger fires
         td.Actions.Add(new ExecAction("my_application.exe", "c:\\test.log", null));

         // Register the task in the root folder
         ts.RootFolder.RegisterTaskDefinition(@"Test", td);

         // Remove the task we just created
         ts.RootFolder.DeleteTask("Test");
      }
   }

You write your my_application.exe for connection API et pull to database. Next, config the task created to call your application.

Quartz is also an option with a richer API to create a task and save it to database. But I think Windows Scheduled tasks might give you all you need.

Upvotes: 2

Related Questions