Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call a method daily, at specific time, in C#?

I've searched on SO and found answers about Quartz.net. But it seems to be too big for my project. I want an equivalent solution, but simpler and (at best) in-code (no external library required). How can I call a method daily, at a specific time?

I need to add some information about this:

  • the simplest (and ugly) way to do this, is check the time every second/minute and call the method, at right time

I want a more-effective way to do this, no need to check the time constantly, and I have control about whether the job is done a not. If the method fails (because of any problems), the program should know to write to log/send a email. That's why I need to call a method, not schedule a job.

I found this solution Call a method at fixed time in Java in Java. Is there a similar way in C#?

EDIT: I've done this. I added a parameter into void Main(), and created a bat (scheduled by Windows Task Scheduler) to run the program with this parameter. The program runs, does the job, and then exits. If a job fails, it's capable of writing log and sending email. This approach fits my requirements well :)

like image 471
Quan Mai Avatar asked Jul 14 '10 04:07

Quan Mai


2 Answers

  • Create a console app that does what you're looking for
  • Use the Windows "Scheduled Tasks" functionality to have that console app executed at the time you need it to run

That's really all you need!

Update: if you want to do this inside your app, you have several options:

  • in a Windows Forms app, you could tap into the Application.Idle event and check to see whether you've reached the time in the day to call your method. This method is only called when your app isn't busy with other stuff. A quick check to see if your target time has been reached shouldn't put too much stress on your app, I think...
  • in a ASP.NET web app, there are methods to "simulate" sending out scheduled events - check out this CodeProject article
  • and of course, you can also just simply "roll your own" in any .NET app - check out this CodeProject article for a sample implementation

Update #2: if you want to check every 60 minutes, you could create a timer that wakes up every 60 minutes and if the time is up, it calls the method.

Something like this:

using System.Timers;  const double interval60Minutes = 60 * 60 * 1000; // milliseconds to one hour  Timer checkForTime = new Timer(interval60Minutes); checkForTime.Elapsed += new ElapsedEventHandler(checkForTime_Elapsed); checkForTime.Enabled = true; 

and then in your event handler:

void checkForTime_Elapsed(object sender, ElapsedEventArgs e) {     if (timeIsReady())     {        SendEmail();     } } 
like image 198
marc_s Avatar answered Sep 22 '22 15:09

marc_s


I created a simple scheduler that is easy to use and you do not need to use external library. TaskScheduler is a singleton that keeps references on the timers so timers will not be garbage collected, it can schedule multiple tasks. You can set the first run (hour and minute), if at the time of scheduling this time is over scheduling start on the next day this at that time. But it is easy to customize the code.

Scheduling a new task is so simple. Example: At 11:52 the first task is for every 15 secunds, the second example is for every 5 secunds. For daily execution set 24 to the 3 parameter.

TaskScheduler.Instance.ScheduleTask(11, 52, 0.00417,      () =>      {         Debug.WriteLine("task1: " + DateTime.Now);         //here write the code that you want to schedule     });  TaskScheduler.Instance.ScheduleTask(11, 52, 0.00139,     () =>     {         Debug.WriteLine("task2: " + DateTime.Now);         //here write the code that you want to schedule     }); 

My debug window:

task2: 07.06.2017 11:52:00 task1: 07.06.2017 11:52:00 task2: 07.06.2017 11:52:05 task2: 07.06.2017 11:52:10 task1: 07.06.2017 11:52:15 task2: 07.06.2017 11:52:15 task2: 07.06.2017 11:52:20 task2: 07.06.2017 11:52:25 ... 

Just add this class to your project:

public class TaskScheduler {     private static TaskScheduler _instance;     private List<Timer> timers = new List<Timer>();      private TaskScheduler() { }      public static TaskScheduler Instance => _instance ?? (_instance = new TaskScheduler());      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);     } } 
like image 20
jannagy02 Avatar answered Sep 20 '22 15:09

jannagy02