Как я могу запланировать службу Windows С# для выполнения задачи ежедневно?

У меня есть служба, написанная на С# (.NET 1.1), и хочу, чтобы она выполняла некоторые действия по очистке в полночь каждую ночь. Я должен хранить весь код, содержащийся в сервисе, и что это самый простой способ сделать это? Использовать Thread.Sleep() и проверять время перескакивания?

Ответ 1

Я бы не использовал Thread.Sleep(). Либо используйте запланированную задачу (как указывали другие), либо настройте таймер внутри вашей службы, который периодически срабатывает (например, каждые 10 минут) и проверяет, изменилась ли дата с момента последнего запуска:

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

Ответ 2

Отъезд Quartz.NET. Вы можете использовать его в службе Windows. Он позволяет запускать задание на основе настроенного графика и даже поддерживает простой синтаксис "cron job". У меня был большой успех.

Вот краткий пример его использования:

// 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);

Ответ 3

Ежедневная задача? Похоже, что это должна быть запланированная задача (панель управления) - нет необходимости в обслуживании здесь.

Ответ 4

Должен ли он быть фактическим сервисом? Можете ли вы просто использовать встроенные запланированные задачи на панели управления Windows.

Ответ 5

То, как я это делаю, - это таймер.

Запустите таймер сервера, проверьте его час/минуту каждые 60 секунд.

Если это правильный час/минута, запустите процесс.

На самом деле это абстрагировано в базовый класс, который я называю OnceADayRunner.

Позвольте мне немного очистить код, и я отправлю его здесь.

    private void OnceADayRunnerTimer_Elapsed(object sender, ElapsedEventArgs e)
    {
        using (NDC.Push(GetType().Name))
        {
            try
            {
                log.DebugFormat("Checking if it 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();
        }
    }

Говядина метода находится в проверке e.SignalTime.Minute/Hour.

Там есть крючки для тестирования и т.д., но это то, что ваш прошедший таймер мог бы выглядеть так, чтобы все это работало.

Ответ 6

Как уже писали другие, таймер является лучшим вариантом в описанном вами сценарии.

В зависимости от ваших точных требований, проверка текущего времени каждую минуту может не понадобиться. Если вам не нужно выполнять действие точно в полночь, но только через час после полуночи вы можете пойти на Мартин подход, только проверяя, изменилась ли дата.

Если причина, по которой вы хотите совершить свое действие в полночь, заключается в том, что вы ожидаете низкой нагрузки на свой компьютер, лучше позаботьтесь: такое же предположение часто делают другие, и вдруг у вас есть 100 действий по очистке, начинающихся между 0: 00 и 0:01 утра

В этом случае вам следует подумать о том, чтобы начать очистку в другое время. Обычно я делаю это не часами, а в полчаса (1,30 м., Являюсь моим личным предпочтением).

Ответ 7

Я бы предположил, что вы используете таймер, но установите его для проверки каждые 45 секунд, а не минуты. В противном случае вы можете столкнуться с ситуациями, когда с большой нагрузкой проверка на конкретную минуту пропущена, потому что между тем, как таймер запускается и время запуска вашего кода, и проверяет текущее время, возможно, вы пропустили целевую минуту.

Ответ 9

Вот мой кусок кода, который работает:

 protected override void OnStart(string[] args)
    {
            timer = new Timer(); //Initialize the globally declared timer 
            //SETTING THE INTERVAL FROM CONFIG FILE (10 SECONDS)
            timer.Interval = Convert.ToInt32(ConfigurationManager.AppSettings["TimerInterval"]);
            timer.Enabled = true;
            timer.Elapsed += timer_Elapsed;           
    }

В прошедшем событии вы можете сделать это:

private void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
            timer.Enabled = false;           
            string ScheduleTime = GlobalVariables.ScheduledTime;//GETTING SCHEDULED TIME FROM CONFIG IN (HH:mm) FORMAT
            string CurrentHourMin = DateTime.Now.ToString("HH:mm");//GETTING CURRENT TIME IN HH:mm format
            if (ScheduleTime == CurrentHourMin)
            {
               // YOUR CODE 
            }
            System.Threading.Thread.Sleep(60000); //Putting thread to sleep for 60 seconds to skip the current minute to avoid re-execution of code
            timer.Enabled = true;                  
    }

Ответ 10

Попробуйте следующее:

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
    }
}