Comment puis-je programmer un service Windows C # pour effectuer une tâche quotidiennement?

J’ai un service écrit en C # (.NET 1.1) et je souhaite qu’il effectue des actions de nettoyage tous les soirs à minuit. Je dois garder tout le code contenu dans le service, alors quel est le moyen le plus simple d’y parvenir? Utilisation de Thread.Sleep() et vérification du temps écoulé?

Je n’utiliserais pas Thread.Sleep (). Utilisez une tâche planifiée (comme d’autres l’ont mentionné) ou configurez un minuteur dans votre service, qui se déclenche périodiquement (toutes les 10 minutes par exemple) et vérifie si la date a changé depuis la dernière exécution:

 private Timer _timer; private DateTime _lastRun = DateTime.Now.AddDays(-1); protected override void OnStart(ssortingng[] 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(); } } 

Découvrez Quartz.NET . Vous pouvez l’utiliser dans un service Windows. Il vous permet d’exécuter un travail en fonction d’une planification configurée, et prend même en charge une syntaxe simple “cron job”. J’ai eu beaucoup de succès avec ça.

Voici un exemple rapide de son utilisation:

 // 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 sortinggger using the basic cron syntax. // This tells it to run at 1AM every Monday - Friday. var sortinggger = new CronTrigger( "sortinggger1", "group1", "job1", "group1", "0 0 1 ? * MON-FRI"); // Add the job to the scheduler scheduler.AddJob(job, true); scheduler.ScheduleJob(sortinggger); 

Une tâche quotidienne? On dirait qu’il ne devrait s’agir que d’une tâche planifiée (panneau de contrôle) – pas besoin de service ici.

Est-ce que ce doit être un service réel? Pouvez-vous simplement utiliser les tâches planifiées intégrées dans le panneau de configuration de Windows.

La façon dont j’accomplis ceci est avec une timer.

Exécutez une timer de serveur, faites-la vérifier l’heure / minute toutes les 60 secondes.

Si c’est la bonne heure / minute, exécutez votre processus.

Je l’ai en fait extrait dans une classe de base que j’appelle OnceADayRunner.

Laissez-moi nettoyer le code un peu et je le posterai ici.

  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.ToSsortingng()); } OnceADayTimer.Start(); } } 

Le boeuf de la méthode est dans la vérification e.SignalTime.Minute / Hour.

Il y a des crochets là-bas pour les tests, etc., mais voici à quoi pourrait ressembler votre timer écasting pour que tout fonctionne.

Comme d’autres l’ont déjà écrit, une timer est la meilleure option dans le scénario que vous avez décrit.

Selon vos exigences exactes, il peut être inutile de vérifier l’heure actuelle toutes les minutes. Si vous n’avez pas besoin d’exécuter l’action exactement à minuit, mais dans l’heure qui suit après minuit, vous pouvez opter pour l’approche de Martin consistant à vérifier uniquement si la date a changé.

Si la raison pour laquelle vous souhaitez effectuer votre action à minuit est que vous attendez une charge de travail réduite sur votre ordinateur, mieux vaut prendre garde: la même hypothèse est souvent faite par d’autres, et vous avez soudainement 100 actions de nettoyage entre 0:00 et 0 : 01h

Dans ce cas, vous devriez envisager de commencer votre nettoyage à un moment différent. Je fais généralement ces choses pas à l’heure, mais à la demi-heure (13h30 étant ma préférence personnelle)

Je suggère que vous utilisez une timer, mais réglez-le pour vérifier toutes les 45 secondes, pas la minute. Sinon, vous pouvez rencontrer des situations où, avec une charge importante, la vérification d’une minute particulière est manquée, car entre le moment où la timer se déclenche et le moment où votre code s’exécute et l’heure courante, vous avez manqué la minute cible.

Vous pouvez également essayer la TaskSchedulerLibrary ici http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8

Implémenter la classe abstraite AbstractScheduledTask et appeler la méthode statique ScheduleUtilityFactory.AddScheduleTaskToBatch

Pour ceux qui ont trouvé que les solutions ci-dessus ne fonctionnaient pas, c’est parce que vous pouvez avoir this dans votre classe, ce qui implique une méthode d’extension qui, comme le message d’erreur l’indique, n’a de sens que pour une classe statique non générique. Votre classe n’est pas statique. Cela ne semble pas être une méthode logique, car elle agit sur l’instance en question, alors supprimez-la.

Essaye ça:

 public partial class Service : ServiceBase { private Timer timer; public Service() { InitializeComponent(); } protected override void OnStart(ssortingng[] 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 } }