.NET Windows Service с таймером перестает отвечать - PullRequest
18 голосов
/ 29 декабря 2008

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

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:

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

Ответы [ 7 ]

18 голосов
/ 29 декабря 2008

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

обернуть тело кода таймера в блок try-catch

5 голосов
/ 29 декабря 2008

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

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

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

4 голосов
/ 29 декабря 2008

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

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

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

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

3 голосов
/ 07 июля 2011

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

    void TimeLoop(object arg)
    {
        stopTimer();

        //Do some stuff

        startTimer();
    }

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

3 голосов
/ 29 декабря 2008

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

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 и т. Д., Чтобы уменьшить дублирование.

0 голосов
/ 29 декабря 2008

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

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

0 голосов
/ 29 декабря 2008

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...