У меня есть служба, написанная на С# (.NET 1.1), и хочу, чтобы она выполняла некоторые действия по очистке в полночь каждую ночь. Я должен хранить весь код, содержащийся в сервисе, и что это самый простой способ сделать это? Использовать Thread.Sleep()
и проверять время перескакивания?
Как я могу запланировать службу Windows С# для выполнения задачи ежедневно?
Ответ 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 секунд, а не минуты. В противном случае вы можете столкнуться с ситуациями, когда с большой нагрузкой проверка на конкретную минуту пропущена, потому что между тем, как таймер запускается и время запуска вашего кода, и проверяет текущее время, возможно, вы пропустили целевую минуту.
Ответ 8
Вы также можете попробовать TaskSchedulerLibrary здесь http://visualstudiogallery.msdn.microsoft.com/a4a4f042-ffd3-42f2-a689-290ec13011f8
Внедрить абстрактный класс AbstractScheduledTask
и вызвать статический метод ScheduleUtilityFactory.AddScheduleTaskToBatch
Ответ 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
}
}