it-swarm.com.de

Windows-Dienst zum Ausführen einer Funktion zur angegebenen Zeit

Ich wollte einen Windows-Dienst starten, um täglich zu einer bestimmten Zeit eine Funktion auszuführen. 

Welche Methode sollte ich in Betracht ziehen, um dies zu implementieren? Timer oder mit Threads?

19
Ziyad Ahmad

(1) Stellen Sie _timer.Interval beim ersten Start auf die Anzahl von Millisekunden zwischen Dienststart und Zeitplan ein. In diesem Beispiel wurde die Zeit für den Zeitplan auf 7:00 Uhr als _scheduleTime = DateTime.Today.AddDays (1) .AddHours (7) festgelegt. 

(2) Setzen Sie bei Timer_Elapsed _timer.Interval auf 24 Stunden (in Millisekunden) zurück, wenn das aktuelle Intervall nicht 24 Stunden beträgt. 

System.Timers.Timer _timer;
DateTime _scheduleTime; 

public WinService()
{
    InitializeComponent();
    _timer = new System.Timers.Timer();
    _scheduleTime = DateTime.Today.AddDays(1).AddHours(7); // Schedule to run once a day at 7:00 a.m.
}

protected override void OnStart(string[] args)
{           
    // For first time, set amount of seconds between current time and schedule time
    _timer.Enabled = true;
    _timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;                                          
    _timer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
}

protected void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
    // 1. Process Schedule Task
    // ----------------------------------
    // Add code to Process your task here
    // ----------------------------------


    // 2. If tick for the first time, reset next run to every 24 hours
    if (_timer.Interval != 24 * 60 * 60 * 1000)
    {
        _timer.Interval = 24 * 60 * 60 * 1000;
    }  
}

Bearbeiten:

Manchmal möchten die Leute, dass der Dienst am Tag 0 beginnt, und nicht morgen, damit sie DateTime.Today.AddDays(0) ändern. Wenn sie dies tun und eine Zeit in der Vergangenheit einstellen, führt dies zu einem Fehler beim Festlegen des Intervalls mit einer negativen Zahl.

//Test if its a time in the past and protect setting _timer.Interval with a negative number which causes an error.
double tillNextInterval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;
if (tillNextInterval < 0) tillNextInterval += new TimeSpan(24, 0, 0).TotalSeconds * 1000;
_timer.Interval = tillNextInterval;
63
Settapon H

Gute Antwort (ich habe Ihren Code verwendet), aber ein Problem mit dieser Zeile:

_timer.Interval = _scheduleTime.Subtract(DateTime.Now).TotalSeconds * 1000;

Wenn DateTime.now jenseits von scheduleTime liegt, werden Sie negativ und dies generiert eine Ausnahme, wenn Sie timer.Interval zuweisen.

Ich benutzte:

if (DateTime.now > scheduleTime)
    scheduleTime = scheduleTime.AddHours(24);

Dann die Subtraktion durchführen.

6
Evan

Verwenden Sie den in Windows integrierten Taskplaner ( http://windows.Microsoft.com/de-de/windows7/schedule-a-task ) oder Quartz.net.

Es sei denn ... Sie haben einen Dienst, der viele andere Verarbeitungsvorgänge durchführt und ständig ausgeführt werden muss. In diesem Fall ist ein Timer möglicherweise angebracht. 

3
Ian Mercer

Sind Sie sicher, dass Sie einen Dienst benötigen, der nur einmal pro Tag ausgeführt wird?

Vielleicht ist Windows Task Schedule eine bessere Lösung?

2

Sie können es mit einem Thread und einem Ereignis tun; ein Timer ist nicht erforderlich.

using System;
using System.ServiceProcess;
using System.Threading;

partial class Service : ServiceBase
{
    Thread Thread;

    readonly AutoResetEvent StopEvent;

    public Service()
    {
        InitializeComponent();

        StopEvent = new AutoResetEvent(initialState: false);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            StopEvent.Dispose();

            components?.Dispose();
        }

        base.Dispose(disposing);
    }

    protected override void OnStart(string[] args)
    {
        Thread = new Thread(ThreadStart);

        Thread.Start(TimeSpan.Parse(args[0]));
    }

    protected override void OnStop()
    {
        if (!StopEvent.Set())
            Environment.FailFast("failed setting stop event");

        Thread.Join();
    }

    void ThreadStart(object parameter)
    {
        while (!StopEvent.WaitOne(Timeout(timeOfDay: (TimeSpan)parameter)))
        {
            // do work here...
        }
    }

    static TimeSpan Timeout(TimeSpan timeOfDay)
    {
        var timeout = timeOfDay - DateTime.Now.TimeOfDay;

        if (timeout < TimeSpan.Zero)
            timeout += TimeSpan.FromDays(1);

        return timeout;
    }
}
0
drowa
private static double scheduledHour = 10;
private static DateTime scheduledTime;

public WinService()
{
     scheduledTime = DateTime.Today.AddHours(scheduledHour);//setting 10 am of today as scheduled time- service start date
}

private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
      DateTime now = DateTime.Now;
      if (scheduledTime < DateTime.Now)
      {
         TimeSpan span = now - DateTime.Now;
         scheduledTime = scheduledTime.AddMilliseconds(span.Milliseconds).AddDays(1);// this will set scheduled time to 10 am of next day while correcting the milliseconds
         //do the scheduled task here
      }  
}
0
Binish Babu