Запланированное выполнение службы Windows
Если у меня есть служба Windows, которая должна выполнять задачу каждые 30 секунд, что лучше использовать; класс Timer() или цикл, который выполняет задачу, а затем спит в течение нескольких секунд?
class MessageReceiver
{
public MessageReceiver()
{
}
public void CommencePolling()
{
while (true)
{
try
{
this.ExecuteTask();
System.Threading.Thread.Sleep(30000);
}
catch (Exception)
{
// log the exception
}
}
}
public void ExecutedTask()
{
// do stuff
}
}
class MessageReceiver
{
public MessageReceiver()
{
}
public void CommencePolling()
{
var timer = new Timer()
{
AutoReset = true,
Interval = 30000,
Enabled = true
};
timer.Elapsed += Timer_Tick;
}
public void Timer_Tick(object sender, ElapsedEventArgs args)
{
try
{
// do stuff
}
catch (Exception)
{
// log the exception
}
}
}
Служба Windows создаст экземпляр класса MessageReciever и выполнит метод CommencePolling в новом потоке.
5 ответов
Я думаю, что это действительно зависит от вашего требования.
Случай 1. Предположим, вы хотите запустить this.ExecuteTask()
каждые пять минут, начиная с 12:00 (т.е. 12:00, 12:05, ...), и предположим, что время выполнения this.ExecuteTask()
варьируется (например, от 30 секунд до 2 минут), возможно использование таймера вместо Thread.Sleep() кажется более простым способом сделать это (по крайней мере, для меня).
Тем не менее, вы можете добиться этого поведения с Thread.Sleep()
а также путем вычисления смещения при получении меток времени при пробуждении потока и при завершении this.ExecuteTask()
,
Случай 2. Предположим, вы хотите выполнить задачу в течение следующих 5 минут, сразу после завершения this.ExecuteTask()
, с помощью Thread.Sleep()
кажется проще. Опять же, вы можете добиться этого поведения и с помощью таймера, сбрасывая таймер каждый раз, одновременно вычисляя смещения this.ExecuteTask()
завершается.
Примечание 1, для случая 1 вы должны быть очень осторожны в следующем сценарии: что если this.ExecuteTask()
иногда занимает больше, чем период (то есть начинается в 12:05 и заканчивается в 12:13 в приведенном выше примере).
Что это значит для вашего приложения и как оно будет обрабатываться?
а. Полный отказ - прервать службу или прервать текущее (12:05) выполнение в 12:10 и запустить 12:10.
б. Ничего страшного (пропустите 12:10 и бегитеthis.ExecuteTask()
в 12:15).с. Ничего страшного, но нужно запускать выполнение в 12:10 сразу после завершения задачи в 12:05 (что, если это займет более 5 минут??).
д. Необходимо запустить выполнение 12:10, даже если в данный момент выполняется 12:05.
е. что-нибудь еще?
Для политики, которую вы выбрали выше, ваш выбор реализации (таймер или
Thread.Sleep()
) легко поддержать вашу политику?
Примечание2. В.NET можно использовать несколько таймеров. Пожалуйста, ознакомьтесь со следующим документом (хотя он немного устарел, но кажется, что это хорошее начало): Сравнение классов таймеров в библиотеке классов.NET Framework
Не ответил я, но Джон Сондерс (см. Выше)... ответ можно найти здесь. Для службы Windows, что лучше, ожидание или таймер?
Вы делаете что-нибудь еще в течение этого десяти секундного ожидания? Использование Thread.sleep будет блокировать, мешая вам делать другие вещи. С точки зрения производительности, я не думаю, что вы увидите слишком много различий, но я бы сам не использовал Thread.sleep.
Есть три таймера на выбор - System.Windows.Forms.Timer реализован в главном потоке, тогда как System.Timers.Timer и System.Threading.Timer создают отдельные потоки.
Я считаю, что оба метода эквивалентны. Поток будет в любом случае: либо потому, что вы его создаете, либо потому, что библиотека, реализующая класс Timer, создает его.
Использование класса Timer может быть немного менее затратным с точки зрения ресурсов, поскольку поток, реализующий таймеры, вероятно, отслеживает и другие тайм-ауты.