C # Windows Service Timeout при запуске - PullRequest
16 голосов
/ 10 августа 2011

У меня проблемы с попыткой определить причину тайм-аута в службе Windows, которую я создал с помощью C #. Я потратил значительное количество времени на просмотр нескольких сообщений и тем по этой проблеме, но я не уверен, что еще можно попробовать.

В чем проблема?

Иногда на некоторых машинах, на которых запущена моя служба Windows, она не запускается успешно после перезагрузки машины. Я получаю обычные сообщения EventLog о том, что служба не запускается своевременно и время ожидания истекло после 30000 миллисекунд. Компьютеры с Windows Server 2003 кажутся наиболее распространенным шаблоном, но не всегда изолированы только от этой ОС. Например, он отлично работает на других машинах W2K3.

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

Другие детали:

  1. Служба Windows написана на C # и использует .Net 2.0
  2. Нет других зависимостей сервиса для моего сервиса, когда установлен.
  3. Служба exe является сборкой выпуска без подписи или аутентификации подписания.
  4. Метод OnStart выполняется максимально быстро, создавая Нить и запуск этой нити. Никакой другой инициализации не происходит в пределах OnStart.
  5. Когда служба фактически не запускается, открытие служб список и запуск его вручную каждый раз работает и сервис начинается, вероятно, менее чем за секунду.

В мой Program.cs добавлен следующий код, который включает в себя основную точку входа для службы. Я подключаюсь к событию UnhandledException на CurrentDomain и использую log4net для записи любых необработанных ошибок Есть также попытка / отлов вокруг ServiceBase.Run, если он каким-то образом разорвется, чтобы я мог записать эту ошибку.

static void Main()
{
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[] 
    { 
        new SchedulerService() 
    };

    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);

    try
    {
        ServiceBase.Run(ServicesToRun);
    }
    catch (Exception ex)
    {
        Log.Fatal("Unhandled Service Exception", ex);
    }
}

private static log4net.ILog _log = null;
static log4net.ILog Log
{
    get
    {
        if (_log == null)
        {
            if (!log4net.LogManager.GetRepository().Configured)
            {
                log4net.Config.XmlConfigurator.Configure();
            }

            _log = log4net.LogManager.GetLogger(typeof(Program));
        }
        return _log;
    }
}

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    Exception ex = e.ExceptionObject as Exception;
    if (ex == null) ex = new Exception(e.ExceptionObject.ToString());

    Log.Fatal("Unhandled Service Exception", ex);
}

Код в моей унаследованной реализации ServiceBase выглядит следующим образом:

protected override void OnStart(string[] args)
{
    Thread serviceThread = new Thread(new ThreadStart(BackgroundStart));
    serviceThread.IsBackground = true;
    serviceThread.Start();
}

private void BackgroundStart()
{
    //Initialize and start worker objects to perform monitoring...
    //<Snip>
}

Моя реализация log4net использует ConsoleAppender и RollingFileAppender, где его сведения о конфигурации хранятся в App.config.

На данном этапе я не уверен, что еще можно попробовать. Если потребуется дополнительная информация, дайте мне знать.

Спасибо.

Обновление: Просто чтобы обновить всех, я собираюсь попробовать некоторые из предложений, таких как прямой вход в EventLog или файл вместо Log4Net, чтобы увидеть, является ли это причиной. Я также попытаюсь установить для generatePublisherEvidence в app.config значение false. Я просто жду подходящего времени простоя для доступа к клиентскому серверу, чтобы проверить эти вещи.

Ответы [ 5 ]

7 голосов
/ 11 августа 2011

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

<runtime>
    <generatePublisherEvidence enabled="false" />
</runtime>

Также рекомендуется в этом источнике MSDN :
«Мы рекомендуем сервисам использовать этот элемент для улучшения производительности запуска. Использование этого элемента также может помочь избежать задержек, которые могут привести к тайм-ауту и ​​отмене запуска сервиса

2 голосов
/ 10 августа 2011

Несколько вещей, чтобы попробовать:

  • Добавить сообщения журнала в начало Main(), до ServiceBase.Run() и т. Д. Если вы получили файл журнала, как эти метки времени сравниваются с журналом событий Windows?

  • Создайте новый сервис с помощью мастера новых проектов и разверните его как есть. На проблемных машинах он запускается надежно?

  • Получите монитор процесса и наблюдайте за нормальным запуском. Ищите любую неожиданную сеть или файловый ввод / вывод.

  • Убедитесь, что ваш SchedulerService не выполняет никакой работы в конструкторе и не имеет статически инициализированных зависимостей.

  • Установите параметры восстановления для перезагрузки при первом сбое. Надежно ли это работает?

1 голос
/ 10 августа 2011

Я также подозреваю, что log4net как-то зависает. Возможно, диск, на котором будет создан журнал, еще не готов к загрузке машины. Вы пытались начать обслуживание с задержкой?

enter image description here

1 голос
/ 10 августа 2011

Как правило, порождение фонового потока из OnStart является правильным решением.

В целях устранения неполадок вы можете попытаться увеличить время запуска службы, вызвав RequestAdditionalTime метод от OnStart.Кроме того, вы можете проверить, были ли какие-либо сообщения записаны в журнал событий Windows (журнал «Приложение», источником должно быть имя вашей службы).

0 голосов
/ 10 августа 2011

Поскольку log4net не предназначен для ( по их словам ) надежной системы ведения журналов, я подумал, что было бы неплохо записывать необработанные исключения в журнал событий (а также в ваш журнал), особенно сСервисы.

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