J'ai un service écrit en C # (.NET 1.1) et je souhaite qu'il effectue des actions de nettoyage à minuit tous les soirs. Je dois conserver tout le code contenu dans le service, alors quel est le moyen le plus simple d'y parvenir? Utilisation Thread.Sleep()
et vérification du temps écoulé?
c#
windows-services
scheduling
scheduled-tasks
ctrlalt3nd
la source
la source
Réponses:
Je n'utiliserais pas Thread.Sleep (). Soit utilisez une tâche planifiée (comme d'autres l'ont mentionné), soit configurez un minuteur dans votre service, qui se déclenche périodiquement (toutes les 10 minutes par exemple) et vérifiez 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(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(); } }
la source
Découvrez Quartz.NET . Vous pouvez l'utiliser dans un service Windows. Il vous permet d'exécuter un travail basé sur une planification configurée, et il prend même en charge une simple syntaxe de «tâche cron». 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 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);
la source
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 d'un service ici.
la source
Doit-il s'agir d'un service réel? Pouvez-vous simplement utiliser les tâches planifiées intégrées dans le panneau de configuration de Windows.
la source
La façon dont j'accomplis cela est avec une minuterie.
Exécutez une minuterie de serveur, demandez-lui de vérifier l'heure / minute toutes les 60 secondes.
Si c'est la bonne heure / minute, exécutez votre processus.
En fait, je l'ai résumé dans une classe de base que j'appelle OnceADayRunner.
Laissez-moi nettoyer un peu le code 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.ToString()); } OnceADayTimer.Start(); } }
Le bœuf de la méthode est dans le contrôle e.SignalTime.Minute / Hour.
Il y a des crochets là-dedans pour les tests, etc.
la source
Comme d'autres l'ont déjà écrit, une minuterie est la meilleure option dans le scénario que vous avez décrit.
En fonction de vos besoins exacts, la vérification de l'heure actuelle toutes les minutes peut ne pas être nécessaire. Si vous n'avez pas besoin d'effectuer l'action exactement à minuit, mais juste dans l'heure qui suit 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 vous attendez à une faible charge de travail sur votre ordinateur, mieux vaut faire attention: la même hypothèse est souvent faite par d'autres, et tout à coup vous avez 100 actions de nettoyage qui démarrent entre 0:00 et 0. : 01 h
Dans ce cas, vous devriez envisager de commencer votre nettoyage à un autre moment. Je fais généralement ces choses non pas à l'heure d'horloge, mais à une demi-heure (1,30 étant ma préférence personnelle)
la source
Je vous suggère d'utiliser une minuterie, mais de la régler pour qu'elle vérifie toutes les 45 secondes, pas les minutes. Sinon, vous pouvez rencontrer des situations où, avec une charge lourde, la vérification d'une minute particulière est manquée, car entre le moment où le minuteur se déclenche et le moment où votre code s'exécute et vérifie l'heure actuelle, vous avez peut-être manqué la minute cible.
la source
Vous pouvez également essayer la TaskSchedulerLibrary ici http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8
Implémentez la classe abstraite
AbstractScheduledTask
et appelez laScheduleUtilityFactory.AddScheduleTaskToBatch
méthode statiquela source
Pour ceux qui ont trouvé que les solutions ci-dessus ne fonctionnaient pas, c'est parce que vous pouvez avoir un à l'
this
intérieur de votre classe, ce qui implique une méthode d'extension qui, comme le message d'erreur l'indique, n'a de sens que sur une classe statique non générique. Votre classe n'est pas statique. Cela ne semble pas être quelque chose qui a du sens en tant que méthode d'extension, car il agit sur l'instance en question, supprimez donc lethis
.la source
Essaye ça:
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 } }
la source