Приложение службы Windows зависает - PullRequest
2 голосов
/ 13 марта 2011

Справочная информация:
- Запуск Windows Server 2008 R2.
- Серверы были исправлены всеми последними обновлениями.
- На сервере запущено 5 служб, встроенных в .NET 3.5, и все эти службы используют таймеры для повторной проверки базы данных (в основном каждые 10 секунд).
- Эти службы не интенсивно используют ЦП и ОЗУ. - Сервер не имеет проблем с производительностью, ресурсами или узкими местами.

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

Это поведение непредсказуемо, иногда требуется неделя или месяц, прежде чем оно перестает работать. Кроме того, иногда службы «умирают» все вместе или только некоторые из них одновременно.

Единственное, что приходило мне в голову, это объект Таймера. Я использовал System.Timers.Timer и обнаружил несколько веток форума, заявляющих, что это ненадежно, поскольку сборщик мусора может освободить экземпляр. Я пытался сохранить его с помощью GC.KeepAlive () безрезультатно. Я следовал нескольким советам по перемещению System.Timers.Timer в System.Threading.Timer, но это тоже не имело никакого значения.

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

Спасибо за любой совет, который может привести к любому решению.

ОБНОВЛЕНИЕ: включая код текущего состояния:

private System.Threading.Timer timerPublish = null;
private bool timerDelegateMethodRunning = false;

protected override void OnStart(string[] args)
{
    SetupTimer();
}

protected override void OnStop()
{
    if (timerPublish != null)
    {
        timerPublish.Dispose();
    }
}

public void SetupTimer()
{
    if (timerPublish != null)
    {
        timerPublish.Dispose();
    }
    TimerCallback callbackMethod = new TimerCallback(this.timerPublish_Elapsed);
    timerPublish = new System.Threading.Timer(callbackMethod, null, 5000, 5000);
}

void timerPublish_Elapsed(Object stateInfo)
{
    if (timerDelegateMethodRunning)
    {
        return;
    }
    timerDelegateMethodRunning = true;

    try
    {
        // Processing code here
    }
    finally
    {
        timerDelegateMethodRunning = false;
    }
}



ОБНОВЛЕНИЕ2: Спасибо вам, ребята, за ваши идеи и советы. Я попытаюсь отладить службы на производственном сервере, как только проблема повторится. Я сообщу, как только у меня будет что-нибудь новое (вероятно, через несколько недель).

Ответы [ 3 ]

3 голосов
/ 13 марта 2011

Почему вы все усложняете? :) Просто используйте метод Timer.Change() для повторного запуска таймера, когда вы будете готовы.

Также знайте, что любые необработанные исключения в WorkerMethod будут f * закупать ваши услуги.

public class YourService
{
    private System.Threading.Timer _timer;

    protected override void OnStart(string[] args)
    {
        //run once in 5 seconds.
        _timer = new System.Threading.Timer(WorkerMethod, null, 5000, Timeout.Infinite);
    }

    protected override void OnStop()
    {
        if (_timer != null)
        {
            _timer.Dispose();
            _timer = null;
        }
    }

    void WorkerMethod(object state)
    {
        // Processing code here

        _worker.Change(5000, Timeout.Infinite); //Run again in 5 seconds
    }
}

Обновление

Я видел, что вы использовали System.Timers.Timer. Самая большая проблема в том, что он игнорирует исключения . То есть, если ваш код выдает исключение, а вы его не перехватываете: , вы никогда не узнаете об этом исключении . Это может быть вашей проблемой.

1 голос
/ 13 марта 2011

Никогда не делайте вывод слишком рано, пока не узнаете, что является причиной зависаний.Могут быть разные невероятные факторы, но анализ дампа или отладка в реальном времени могут сказать вам правду:

http://blogs.msdn.com/b/tess/archive/2006/10/16/net-hang-debugging-walkthrough.aspx

Если хотите, вы можете даже открыть службу поддержки через http://support.microsoft.com

0 голосов
/ 13 марта 2011

В любом случае, я мог бы предложить слегка измененную схему для вашего обслуживания; где у нас есть readonly Timer, который после первоначального назначения просто заставляет переключать для запуска в противоположность тому, как происходит удаление в минуту, а также сохраняет собственную жесткую ссылку на TimerCallback. И, наконец, мы оставляем утилизацию объектов до самого обслуживания (по крайней мере, долгосрочные объекты, о которых мы беспокоимся).

Хотя в вашем случае этот шаблон не может быть белым кроликом из шляпы, я могу ручаться за надежность многих услуг, созданных таким образом. Поэтому, если проблемы возникают даже после их реализации, я с большой уверенностью могу сказать, что то, что следует // Processing code here, само по себе проблематично.

private readonly System.Threading.Timer Timer = null;
private readonly System.Threading.TimerCallback Callback = null;
private readonly int Interval = 5000;

public MyService()
{
    Callback = new TimerCallback(this.timerPublish_Elapsed);
    Timer = new System.Threading.Timer(Callback, null, Timeout.Infinite, Timeout.Infinite);
}

private void Start()
{
    Timer.Change(Timespan.Zero, Interval);
}

private void Stop()
{
    Timer.Change(Timeout.Inifinite, Timeout.Inifnite);
}

protected override void OnStart(string[] args)
{
    Start();
}

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

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
    if(disposing)
    {
        if(Timer != null)
            Timer.Dispose();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...