Подтвердить что ты не робот

Служба Windows Windows с таймером перестает отвечать

У меня есть служба Windows, написанная на С#. Он имеет таймер внутри, который регулярно выполняет некоторые функции. Итак, скелет моего сервиса:

public partial class ArchiveService : ServiceBase
{
    Timer tickTack;
    int interval = 10;
    ...

    protected override void OnStart(string[] args)
    {
        tickTack = new Timer(1000 * interval);

        tickTack.Elapsed += new ElapsedEventHandler(tickTack_Elapsed);
        tickTack.Start();
    }

    protected override void OnStop()
    {            
        tickTack.Stop();
    }    

    private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
    {
        ...
    }
}

Он работает некоторое время (например, 10-15 дней), затем он останавливается. Я имею в виду, что сервис показывает, как работает, но он ничего не делает. Я делаю некоторые протоколирования, и проблема может быть таймером, потому что после интервала он не вызывает функцию tickTack_Elapsed.

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

Таймер используется из пространства имен System.Timers, среда - это Windows 2003. Я использовал этот подход в двух разных службах на разных серверах, но оба они производят это поведение (поэтому я думал, что он каким-то образом связан с мой код или сама структура).

Кто-то испытал такое поведение? Что может быть неправильным?


Edit:

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


Edit:

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

4b9b3361

Ответ 1

Как и многие респонденты отметили, что исключения проглатываются таймером. В моих службах Windows я использую System.Threading.Timer. Он имеет метод Change (...), который позволяет вам запускать/останавливать этот таймер. Возможным местом для исключения может быть проблема с повторной регистрацией - в случае, если tickTack_Elapsed выполняется дольше, чем период таймера. Обычно я пишу таймер так:

    void TimeLoop(object arg)
    {
        stopTimer();

        //Do some stuff

        startTimer();
    }

Вы также можете lock(...) использовать свой основной цикл для защиты от повторного размещения.

Ответ 2

необработанные исключения в таймерах проглатываются, и они молча убивают таймер

оберните тело вашего кода таймера в блок try-catch

Ответ 3

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

В другие моменты... Я не думаю, что в таймере есть что-то "элегантное". Для меня это более прямолинейно, чтобы увидеть циклическую операцию в коде, чем методы таймера. Но Элегантность субъективна.

Проблема с памятью? Нет, если вы правильно напишете. Возможно, нагрузка процессора, если ваш Thread.Sleep() не установлен правильно.

Ответ 4

http://support.microsoft.com/kb/842793

Это известная ошибка, которая неоднократно появлялась в Framework.

Самая известная работа: не используйте таймеры. Я сделал эту ошибку неэффективной, выполняя глупый цикл while (true).

Ваш пробег может отличаться, поэтому проверьте свою комбинацию битов OS/Framework.

Ответ 5

Интересная проблема. Если это действительно справедливое время (то есть не исключение), то мне интересно, можете ли вы просто периодически перерабатывать таймер - i.e.

private void tickTack_Elapsed(object sender, ElapsedEventArgs e)
{
    CheckForRecycle();
    // ... actual code
}

private void CheckForRecycle()
{
    lock(someLock) {
        if(++tickCount > MAX_TICKS) {
            tickCount = 0;
            tickTack.Stop();
            // re-create timer
            tickTack = new Timer(...);
            tickTack.Elapsed += ...
            tickTack.Start();
        }
    }
}

Вы могли бы объединить куски этого с помощью OnStart/OnStop и т.д., чтобы уменьшить дублирование.

Ответ 6

Вы проверили журналы ошибок? Может быть, у вас закончились таймеры. Возможно, вы можете создать только один таймер при инициализации ArchiveService и пропустить материал OnStart.

Ответ 7

Я сделал то же самое, что и вы в нескольких проектах, но не имел проблемы.

У вас есть код в tickTac_Elapsed, который может быть причиной этого? Как цикл, который никогда не заканчивается или некоторая ошибка, которая останавливает таймер, используя потоки и ожидая окончания этих и т.д.?