Как иметь петлю в службе Windows без использования таймера
Я хочу вызвать метод бизнес-уровня из службы Windows (выполняется с использованием С# и .NET) через каждые 10 секунд. Однако я не хочу использовать событие Timer_Elapsed, поскольку он запускает другой поток/процесс, если первый поток/процесс все еще запущен. Мне просто нужен однопоточный подход, поскольку несколько вызовов одного и того же метода Business создают нежелательные осложнения.
Итак, я добавил цикл do-while в on_start. Я знаю, что это неверно, поскольку он порождает этот процесс, который становится сиротой, если служба отключена.
Как я могу подойти к этой проблеме?
С уважением,
Чак
Ответы
Ответ 1
В другом способе выполнения тайм-аута метод WaitHandle.WaitOne() предоставляет аргумент тайм-аута. Это очень хорошо работает в сервисе, поскольку позволяет реализовать необходимость остановки службы и периодического выполнения в одном вызове метода. Шаблон выглядит следующим образом:
Thread Worker;
AutoResetEvent StopRequest = new AutoResetEvent(false);
protected override void OnStart(string[] args) {
// Start the worker thread
Worker = new Thread(DoWork);
Worker.Start();
}
protected override void OnStop() {
// Signal worker to stop and wait until it does
StopRequest.Set();
Worker.Join();
}
private void DoWork(object arg) {
// Worker thread loop
for (;;) {
// Run this code once every 10 seconds or stop right away if the service
// is stopped
if (StopRequest.WaitOne(10000)) return;
// Do work...
//...
}
}
Ответ 2
Используйте таймер, но как только вы введете метод обработчика таймера, отключите таймер, чтобы больше не возникало событий. Незадолго до выхода из обработчика снова включите таймер.
Ответ 3
Просмотрите эту дискуссию и, в частности, ответ jsw. Он предлагает механизм синхронизации для предотвращения множественных одновременных вызовов бизнес-логики. Просто отключить таймер в методе обработчика Elapsed
не гарантируется, чтобы предотвратить параллельные вызовы, поскольку обработчик вызывается в отдельном потоке. Используйте блокировку, как предлагает jsw, и остановите таймер в синхронизированном блоке кода.
В качестве альтернативы вы можете использовать Timer
и установить для свойства AutoReset
значение false
. Таким образом, событие Elapsed
создается только один раз, и вы можете reset таймер вручную в конце метода обработчика.
Ответ 4
while(true)
{
..do something
Thread.sleep( some time or day);
}
Ответ 5
Thread thread;
private void DoWork(object arg)
{
while (true)
{
// Run this code once every 20 seconds or stop if the service is stopped
try
{
Thread.Sleep(20000);
//Do work....
}
catch(ThreadInterruptedException)
{
return;
}
}
}
protected override void OnStart(string[] args)
{
// Start the thread
thread = new Thread(DoWork);
mWorker.Start();
}
protected override void OnStop()
{
// interrupt thread and wait until it does
thread.Interrupt();
thread.Join();
}