Comment puis-je programmer un Service c# Windows pour effectuer une tâche quotidienne?

j'ai un service écrit en C# (.NET 1.1) et je veux qu'il effectue des actions de nettoyage à minuit tous les soirs. Je dois garder tout le code contenu dans le service, quelle est la meilleure façon d'accomplir cette? Utilisation de Thread.Sleep() et vérification de l'Heure de retournement?

79
demandé sur Jon Seigel 2009-02-02 18:21:07

10 réponses

Je n'utiliserais pas de fil.Dormir.)( Soit utiliser une tâche programmée (comme d'autres l'ont mentionné), soit configurer un minuteur dans votre service, qui s'allume périodiquement (toutes les 10 minutes par exemple) et vérifier 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();
    }
}
85
répondu M4N 2014-07-04 12:53:27

Check out Quartz.NET . Vous pouvez l'utiliser dans le cadre D'un service Windows. Il vous permet d'exécuter un travail basé sur un programme configuré, et il supporte même une syntaxe simple "cron job". J'ai eu beaucoup de succès avec elle.

voici un exemple rapide de son usage:

// 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);
69
répondu jeremcc 2009-02-02 20:08:48

une tâche quotidienne? Sonne comme il devrait juste être une tâche planifiée (panneau de contrôle) - pas besoin d'un service.

20
répondu Marc Gravell 2009-02-02 15:27:29

doit-il s'agir d'un service réel? Pouvez-vous juste utiliser les tâches programmées intégrées dans le panneau de contrôle windows.

15
répondu Ian Jacobs 2009-02-02 15:26:51

la façon dont je réalise ceci est avec un minuteur.

exécuter un minuteur de serveur, le faire vérifier L'Heure/Minute toutes les 60 secondes.

si c'est la Bonne Heure/Minute, alors exécutez votre processus.

en fait, j'ai fait ce résumé dans une classe de base que j'appelle une fois.

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 e.SignalTime.Minutes/Heures.

il y a des crochets pour les essais, etc. mais c'est ce que votre temps écoulé pourrait ressembler à tout faire fonctionner.

3
répondu CubanX 2009-02-02 15:26:03

Comme d'autres déjà écrit, une minuterie est la meilleure option dans le scénario que vous avez décrit.

selon vos besoins précis, il n'est peut-être pas nécessaire de vérifier l'heure actuelle à chaque minute. Si vous n'avez pas besoin d'effectuer l'action exactement à minuit, mais juste une heure après minuit, vous pouvez aller pour L'approche de Martin de vérifier seulement si la date a changé.

si la raison pour laquelle vous vous voulez effectuer votre action à minuit est que vous vous attendez à une faible charge de travail sur votre ordinateur, mieux prendre soin: la même hypothèse est souvent faite par d'autres, et tout à coup, vous avez 100 actions de nettoyage de démarrage entre 0: 00 et 0: 01 a. m.

Dans ce cas, vous devriez envisager de commencer votre nettoyage à un autre moment. En général, je ne fais pas ces choses à l'heure d'horloge, mais à la demi-heure (1 h 30 du matin étant ma préférence personnelle)

2
répondu Treb 2017-05-23 11:54:44

je vous conseille d'utiliser une minuterie, mais réglez-la pour vérifier toutes les 45 secondes, pas les minutes. Sinon, vous pouvez vous retrouver dans des situations où, avec une charge importante, le contrôle d'une minute particulière est manqué, 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.

1
répondu GWLlosa 2009-02-02 15:36:12

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

mettre en Œuvre la classe abstraite AbstractScheduledTask et appelez le ScheduleUtilityFactory.AddScheduleTaskToBatch la méthode statique

0
répondu Samuel 2017-06-29 12:17:59

pour ceux qui ont trouvé que les solutions ci-dessus ne fonctionnaient pas, c'est parce que vous pouvez avoir un this à l'intérieur de votre classe, ce qui implique une méthode d'extension qui, comme le dit le message d'erreur, 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, puisque cela agit sur l'instance en question, donc supprimer le this .

0
répondu Fandango68 2018-04-24 05:53:09

essayez ceci:

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
    }
}
-2
répondu Shailendra Tiwari 2013-08-09 14:30:19