Come posso programmare un servizio Windows C # per eseguire un’attività quotidianamente?

Ho un servizio scritto in C # (.NET 1.1) e voglio che esegua alcune azioni di pulizia a mezzanotte ogni notte. Devo mantenere tutto il codice contenuto nel servizio, quindi qual è il modo più semplice per farlo? Utilizzo di Thread.Sleep() e controllo del tempo passato a rotazione?

Non userei Thread.Sleep (). O utilizzare un’attività pianificata (come altri hanno menzionato) o impostare un timer all’interno del servizio, che viene triggersto periodicamente (ad esempio ogni 10 minuti) e verificare se la data è cambiata dall’ultima esecuzione:

 private Timer _timer; private DateTime _lastRun = DateTime.Now.AddDays(-1); protected override void OnStart(string[] args) { _timer = new Timer(10 * 60 * 1000); // every 10 minutes _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); _timer.Start(); //... } private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // ignore the time, just compare the date if (_lastRun.Date < DateTime.Now.Date) { // stop the timer while we are running the cleanup task _timer.Stop(); // // do cleanup stuff // _lastRun = DateTime.Now; _timer.Start(); } } 

Controlla Quartz.NET . Puoi usarlo all’interno di un servizio di Windows. Consente di eseguire un lavoro in base a una pianificazione configurata e supporta anche una semplice syntax “cron job”. Ho avuto molto successo con questo.

Ecco un rapido esempio del suo utilizzo:

 // Instantiate the Quartz.NET scheduler var schedulerFactory = new StdSchedulerFactory(); var scheduler = schedulerFactory.GetScheduler(); // Instantiate the JobDetail object passing in the type of your // custom job class. Your class merely needs to implement a simple // interface with a single method called "Execute". var job = new JobDetail("job1", "group1", typeof(MyJobClass)); // Instantiate a trigger using the basic cron syntax. // This tells it to run at 1AM every Monday - Friday. var trigger = new CronTrigger( "trigger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI"); // Add the job to the scheduler scheduler.AddJob(job, true); scheduler.ScheduleJob(trigger); 

Un compito giornaliero? Sembra che dovrebbe essere solo un compito programmato (pannello di controllo) – non c’è bisogno di un servizio qui.

Deve essere un servizio effettivo? Puoi semplicemente usare le attività programmate nel pannello di controllo di Windows.

Il modo in cui lo realizzo è con un timer.

Eseguire un timer del server, fare controllare l’ora / minuto ogni 60 secondi.

Se è la giusta ora / minuto, quindi eseguire il processo.

In realtà ho questo estratto in una class base che chiamo OnceADayRunner.

Fammi pulire un po ‘il codice e lo posterò qui.

  private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e) { using (NDC.Push(GetType().Name)) { try { log.DebugFormat("Checking if it's time to process at: {0}", e.SignalTime); log.DebugFormat("IsTestMode: {0}", IsTestMode); if ((e.SignalTime.Minute == MinuteToCheck && e.SignalTime.Hour == HourToCheck) || IsTestMode) { log.InfoFormat("Processing at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute); OnceADayTimer.Enabled = false; OnceADayMethod(); OnceADayTimer.Enabled = true; IsTestMode = false; } else { log.DebugFormat("Not correct time at: Hour = {0} - Minute = {1}", e.SignalTime.Hour, e.SignalTime.Minute); } } catch (Exception ex) { OnceADayTimer.Enabled = true; log.Error(ex.ToString()); } OnceADayTimer.Start(); } } 

Il manzo del metodo è nel controllo e.SignalTime.Minute / Hour.

Ci sono dei ganci per testare, ecc. Ma questo è il modo in cui il tuo timer potrebbe sembrare funzionare per far funzionare tutto.

Come altri già hanno scritto, un timer è l’opzione migliore nello scenario che hai descritto.

A seconda dei tuoi esatti requisiti, il controllo dell’orario attuale ogni minuto potrebbe non essere necessario. Se non hai bisogno di eseguire l’azione esattamente a mezzanotte, ma solo entro un’ora dopo la mezzanotte, puoi scegliere l’approccio di Martin solo controllando se la data è cambiata.

Se il motivo per cui vuoi eseguire la tua azione a mezzanotte è che ti aspetti un carico di lavoro ridotto sul tuo computer, è meglio fare attenzione: la stessa ipotesi viene spesso fatta da altri, e improvvisamente hai 100 azioni di pulizia che iniziano tra 0:00 e 0 : 01 am

In tal caso, dovresti considerare di iniziare la pulizia in un altro momento. Di solito faccio quelle cose non all’orario, ma alle mezze ore (le 1.30 sono la mia preferenza personale)

Ti suggerirei di utilizzare un timer, ma impostarlo per controllare ogni 45 secondi, non i minuti. In caso contrario, è ansible imbattersi in situazioni in cui con carichi pesanti, il controllo per un minuto particolare viene perso, perché tra il momento in cui il timer si triggers e il tempo in cui il codice viene eseguito e controlla l’ora corrente, potrebbe essere mancato il minuto target.

Puoi anche provare la TaskSchedulerLibrary qui http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8

Implementare la class astratta AbstractScheduledTask e chiamare il metodo statico ScheduleUtilityFactory.AddScheduleTaskToBatch

Per coloro che hanno trovato che le soluzioni di cui sopra non funzionano, è perché si può avere this all’interno della class, il che implica un metodo di estensione che, come dice il messaggio di errore, ha senso solo su una class statica non generica. La tua class non è statica. Questo non sembra essere qualcosa che ha senso come metodo di estensione, dal momento che agisce sull’istanza in questione, quindi rimuovi this .

Prova questo:

 public partial class Service : ServiceBase { private Timer timer; public Service() { InitializeComponent(); } protected override void OnStart(string[] args) { SetTimer(); } private void SetTimer() { if (timer == null) { timer = new Timer(); timer.AutoReset = true; timer.Interval = 60000 * Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]); timer.Elapsed += new ElapsedEventHandler(timer_Elapsed); timer.Start(); } } private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e) { //Do some thing logic here } protected override void OnStop() { // disposed all service objects } }