Выполнение операций по расписанию

542
31 января 2017, 19:49

Необходимо проводить определенные действия по расписанию, абстрактный пример:

  • в понедельник в 12:00 взять файлы из папки
  • во вторник в 13:39 создать папку с файлами
  • в третью пятницу в 7:03 посчитать количество файлов

Целесообразно ли будет для этого использовать timer с Interval в минуту и в его Tick проверять время и день недели?

private void timer1_Tick(object sender, EventArgs e)
{
   var currentTime = DateTime.Now.TimeOfDay;
   var currentDow = DateTime.Now.DayOfWeek;
   var oneMinute = new TimeSpan(0, 1, 0);
   if ((currentDow  == DayOfWeek.Monday)&&(currentTime-timeMonday<oneMinute))
   {
      MondayOperation();  
   }
   if ((currentDow  == DayOfWeek.Tuesday)&&(currentTime-timeTuesday<oneMinute))
   {
      TuesdayOperation();  
   }
   if ((currentDow  == DayOfWeek.Friday)&&(MyDoWInMonth(DateTime.Now).Equals(3))&(currentTime-timeFriday<oneMinute))
   {
      FridayOperation();  
   }
}
Answer 1

Лучше используйте библиотеку Quartz.net, она специально предназначена для таких целей и очень гибко настраивается. Также она есть в nuget:

Install-Package Quartz

Либо можно вообще воспользоваться средствами планировщика задач Windows.

Answer 2

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

Более правильно будет хранить для каждой задачи следующее время запуска и запускать задачу когда текущее время больше запланированного (но не вышло за пределы некоторого разумного интервала). Про строгие сравнения времени забудьте в принципе!

PS для справки - мой старый ответ на смежную тематику: http://ru.stackoverflow.com/a/593736/178779

Answer 3

Я бы разделил программу на 3 модуля и использовал бы стандартный Windows Task Scheduler. Тестировать будет удобнее + всегда понятно, какой компонент работает неверно

Answer 4

Hangfire — планировщик задач для .NET

На мой взгляд это самый лучший многопоточный и масштабируемый планировщик задач. Легкая установка с помощью NuGet

Install-Package Hangfire

С коробки есть красивый дашборд со всей статистикой и всеми запланированными заданиями.

Краткий обзор на habrahabr

Answer 5

Можете посмотреть в сторону TopShelf + Quartz, очень удобно + есть всё что нужно (модули для DI, планирование как угодно).

Для этого Вам нужно будет разделить работы (создать классы производные от IJob), потом описать механизм планирования например так:

private static void ScheduleRepeatableJobIn**<T>(ServiceConfigurator<Service> serviceConfigurator, int timeout) where T : IJob
{
  serviceConfigurator.ScheduleQuartzJob(configurator =>
    configurator.WithSimpleRepeatableSchedule<T>(TimeSpan.From**(timeout), typeof(T).Name));
}

И потом просто запустить сервис/консоль так:

  HostFactory.Run(x =>
      {
        x.Service<Service1>(s =>
        {
          ScheduleRepeatableJobInMinutes<Job1>(s, timeout);
          ScheduleRepeatableJobInMinutes<Job2>(s, timeout);
          s.WhenStarted(tc => tc.Start());
          s.WhenStopped(tc => tc.Stop());
        });
      });

P.S. Пример кода показательный, для решение Вашей проблемы Вам нужно будет написать свою логику планирования.

READ ALSO
Передача параметров в PartialView

Передача параметров в PartialView

Как передать строго типизированный параметр из контроллера в PartialView, при условии что вызов одного и того же PartialView происходит из разных функций...

401
Как заблокировать клавишу в Unity?

Как заблокировать клавишу в Unity?

В моей игре есть пауза, которая вызывается клавишей "Esc"

557
Создание чекбокса для проверки webBrowser (c#)

Создание чекбокса для проверки webBrowser (c#)

Хочу сделать чекбокс, который будет проверять, открыта ли форма webBrowser(те

387
Ошибка компиляции .net6 teamcity

Ошибка компиляции .net6 teamcity

Я пытаюсь скомпельровать проэкт на TeamCity server и получаю следующую ошибку:

369