it-swarm.com.de

Wie kann ich einen C # Windows-Dienst so planen, dass er täglich eine Aufgabe ausführt?

Ich habe einen in C # (.NET 1.1) geschriebenen Dienst und möchte, dass jede Nacht um Mitternacht einige Bereinigungsaktionen ausgeführt werden. Ich muss den gesamten Code im Service enthalten. Wie kann ich das am einfachsten erreichen? Verwendung von Thread.Sleep() und Überprüfung der Zeit, die überrollt wird?

79
ctrlalt3nd

Ich würde Thread.Sleep () nicht verwenden. Verwenden Sie entweder eine geplante Aufgabe (wie von anderen bereits erwähnt) oder richten Sie einen Zeitgeber in Ihrem Dienst ein, der regelmäßig (alle 10 Minuten) ausgelöst wird, und prüfen, ob sich das Datum seit dem letzten Lauf geändert hat:

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
M4N

Check out Quartz.NET . Sie können es in einem Windows-Dienst verwenden. Sie können einen Job basierend auf einem konfigurierten Zeitplan ausführen und unterstützt sogar eine einfache "Cron-Job" -Syntax. Ich hatte viel Erfolg damit.

Hier ist ein schnelles Beispiel für seine Verwendung:

// 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
jeremcc

Eine tägliche Aufgabe? Klingt, als sollte es nur eine geplante Aufgabe sein (Control Panel) - hier ist kein Dienst erforderlich.

20
Marc Gravell

Muss es eine Dienstleistung sein? Können Sie einfach die integrierten geplanten Aufgaben in der Windows-Systemsteuerung verwenden.

15
Ian Jacobs

Die Art und Weise, wie ich dies verwirklichen kann, ist ein Timer.

Führen Sie einen Server-Timer aus, und überprüfen Sie die Stunde/Minute alle 60 Sekunden.

Wenn es die richtige Stunde/Minute ist, führen Sie den Prozess aus.

Ich habe das tatsächlich in eine Basisklasse abstrahiert, die ich OnceADayRunner nenne.

Lassen Sie mich den Code ein wenig bereinigen und ich werde ihn hier posten.

    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();
        }
    }

Das Rindfleisch der Methode befindet sich in der e.SignalTime.Minute/Hour-Prüfung.

Dort gibt es Haken zum Testen usw., aber so könnte Ihr abgelaufener Timer aussehen, damit alles funktioniert.

3
CubanX

Wie andere bereits geschrieben haben, ist ein Timer die beste Option in dem von Ihnen beschriebenen Szenario.

Abhängig von Ihren genauen Anforderungen kann es nicht erforderlich sein, jede Minute die aktuelle Uhrzeit zu überprüfen. Wenn Sie die Aktion nicht genau um Mitternacht ausführen müssen, sondern nur eine Stunde nach Mitternacht, können Sie Martins Ansatz nur prüfen, ob sich das Datum geändert hat.

Wenn Sie Ihre Aktion um Mitternacht ausführen möchten, weil Sie mit einer geringen Arbeitslast auf Ihrem Computer rechnen, achten Sie besser auf die gleiche Annahme: Die gleiche Annahme wird oft von anderen gemacht, und plötzlich gibt es 100 Bereinigungsaktionen, die zwischen 0:00 und 0 beginnen : 01 Uhr.

In diesem Fall sollten Sie die Bereinigung zu einem anderen Zeitpunkt starten. Normalerweise mache ich diese Dinge nicht zur vollen Stunde, sondern zur halben Stunde (um 13:30 Uhr nach meinem persönlichen Geschmack).

2
Treb

Ich würde vorschlagen, dass Sie einen Timer verwenden, aber stellen Sie alle 45 Sekunden ein, nicht die Minute. Andernfalls können Sie auf Situationen stoßen, in denen bei starker Auslastung die Überprüfung für eine bestimmte Minute verpasst wird. Denn zwischen dem Zeitpunkt, an dem der Timer ausgelöst wird, und dem Zeitpunkt, an dem Ihr Code läuft und die aktuelle Uhrzeit abruft, haben Sie möglicherweise die Zielminute verfehlt.

1
GWLlosa

Sie können die TaskSchedulerLibrary auch hier ausprobieren http://visualstudiogallery.msdn.Microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8

Implementieren Sie die abstrakte Klasse AbstractScheduledTask und rufen Sie die statische Methode ScheduleUtilityFactory.AddScheduleTaskToBatch auf

0
Samuel

Bei denjenigen, bei denen die oben genannten Lösungen nicht funktionieren, liegt dies daran, dass sich in Ihrer Klasse möglicherweise eine this befindet, die eine Erweiterungsmethode impliziert, die, wie in der Fehlermeldung angegeben, nur für eine nicht generische statische Klasse Sinn macht. Ihre Klasse ist nicht statisch. Dies scheint als Erweiterungsmethode nicht sinnvoll zu sein, da sie auf die betreffende Instanz einwirkt. Entfernen Sie also die Variable this.

0
Fandango68