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


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

10 79

10 ответов:

Я бы не использовал поток.Сон.)( Либо используйте запланированную задачу (как упоминали другие), либо установите таймер внутри вашего сервиса, который периодически срабатывает (например, каждые 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();
    }
}

проверить 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);

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

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

Я делаю это с помощью таймера.

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

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

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

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

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

говядина метода находится в E.SignalTime.Минутная / часовая проверка.

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

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

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

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

в этом случае вы должны рассмотреть возможность начала очистки в другое время. Я обычно делаю эти вещи не в час ночи, а в полчаса (1.30 утра-мое личное предпочтение)

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

вы также можете попробовать TaskSchedulerLibrary здесь http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8

реализовать абстрактный класс AbstractScheduledTask, а вызов ScheduleUtilityFactory.AddScheduleTaskToBatch статический метод

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

попробуйте это:

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