Служба Windows отключается из-за простоя

Я создал службу Windows vb.net, которая ничего не делает, кроме как пингует веб-службу wcf и обрабатывает отправку запроса на обслуживание этой же веб-службы в ночное время. Он выполняет обе задачи, используя событие таймера. Если служба не делает ничего, кроме этих двух вещей, она говорит при запуске, что отключается из-за простоя. Потоку службы Windows нужно что-то сделать.

Каков наилучший способ предотвратить это отключение, не тратя впустую ресурсы машины? Или я пропустил какую-то настройку в API, чтобы отключить проверку простоя?

Protected Overrides Sub OnStart(ByVal args() As String)
    Dim keepAliveTimer As New System.Timers.Timer(3600000)
    AddHandler keepAliveTimer.Elapsed, AddressOf  IsWebserviceAliveHandler
    keepAliveTimer.AutoReset = True
    keepAliveTimer.Start()
    Dim interval As Integer = Me.CalculateInterval(8, 25)
    Dim timer As New System.Timers.Timer(interval)
    AddHandler timer.Elapsed, AddressOf SendDailyMaintenanceRequestHandler
    timer.AutoReset = True
    timer.Start()
End Sub 

person Community    schedule 22.06.2009    source источник
comment
Как выглядит ваш метод OnStart()?   -  person Rowland Shaw    schedule 22.06.2009
comment
Защищенные переопределения Sub OnStart(ByVal args() As String) Dim keepAliveTimer As New System.Timers.Timer(3600000) AddHandler keepAliveTimer.Elapsed, AddressOf IsWebserviceAliveHandler keepAliveTimer.AutoReset = True keepAliveTimer.Start() Dim interval As Integer = Me.CalculateInterval( 8, 25) Dim timer As New System.Timers.Timer(interval) AddHandler timer.Elapsed, AddressOf SendDailyMaintenanceRequestHandler timer.AutoReset = True timer.Start() End Sub   -  person    schedule 22.06.2009
comment
Было бы интересно увидеть код в SendDailyMaintenanceRequestHandler (или хотя бы его структуру)   -  person Fredrik Mörk    schedule 22.06.2009
comment
Может ли быть так, что объявление таймеров в OnStart приводит к тому, что они удаляются после завершения обработчика OnStart? Это означало бы: нет таймера, нечего делать, простоя, конец...   -  person Thorsten Dittmar    schedule 22.06.2009
comment
@Торстен; таймер нельзя выбрасывать; подписка на событие создает ссылку, поэтому она остается активной, даже если переменная keepAliveTimer выходит за пределы области видимости.   -  person Fredrik Mörk    schedule 22.06.2009
comment
СПАСИБО ВСЕМ, этот сайт самый лучший. Ответ Фредрика был исправлением ... Я хотел оценить его, но у меня нет репутации. Внешняя попытка перехвата является ДОЛЖНОЙ, чтобы убедиться, что вы действительно получаете сообщение об ошибке, когда что-то идет не так. Исключением было то, что CalculateInterval возвращает целое число, в то время как таймеру требуется двойной интервал. В любом случае, я не получил никаких сообщений об ошибках от службы Windows, только сообщение о тайм-ауте простоя. Спасибо вам всем...   -  person    schedule 23.06.2009
comment
Infact... Ошибка была: 23-06-2009 08:31:38 Информация в System.Timers.Timer..ctor(Double interval), но я проверял это.. Это не целое или двойное число.. причина по-видимому, есть автоприведение, но проблема заключалась в том, что мой метод иногда выдавал значение 0. Я думал, что это сразу истечет время таймера. Но на самом деле значение таймера 0 не допускается. Кроме того, это все равно была ошибка, потому что у меня таймер на автосбросе, поэтому он будет зацикливаться.   -  person    schedule 23.06.2009


Ответы (2)


Это должно хорошо работать, если таймер выполняет работу в сервисе. В прошлом году я реализовал своего рода «службу сердцебиения» для проекта. Вот (несколько урезанный) пример кода, как он выглядит:

// assumes that you have using System.Threading; in the top of the file
private Timer _heartbeatTimer;

protected override void OnStart(string[] args)
{
    // the GetTimerInterval function returns an int with the interval (picked
    // up from config file
    _heartbeatTimer = new Timer(HearbeatTimerHandler, null, new TimeSpan(0), 
                                new TimeSpan(0, GetTimerInterval(), 0));
}


private static void HearbeatTimerHandler(object state)
{
    try
    {
        // do the work
    }
    catch (Exception ex)
    {
        // log the exception
    }
}

В нашем случае он регулярно отправляет запрос веб-серверу на запуск веб-приложения, если оно было остановлено (из-за перезапуска или чего-то подобного).

person Fredrik Mörk    schedule 22.06.2009
comment
Я сделал то же самое.. Запустил два таймера, как и вы.. Но в моем случае при запуске службы стартер выдает сообщение что-то вроде Служба была закрыта, в некоторых случаях это происходит из-за того, что он простаивал - person ; 22.06.2009
comment
Удостоверились ли вы, что перехватите любые исключения, которые могут возникнуть? - person Fredrik Mörk; 22.06.2009

В OnStart создайте новый поток, который зацикливается до тех пор, пока служба не будет остановлена. Он выполняет свою задачу, а затем ждет некоторое время. Таким образом, служба не остановится.

Следующее будет псевдокодом для метода потока:

while (!serviceStopped)
{
    try
    {
        PerformTask();
        Thread.Sleep(24 * 60 * 60000); // Wait 24 hours
    }
    catch (ThreadAbortException)
    {
       break;
    }
    catch
    {
       // Log errors
    }
}
person Thorsten Dittmar    schedule 22.06.2009
comment
Я пробовал это... но моя задача выполняется слишком быстро... Кажется, запуск службы нуждается в занятом потоке, чтобы перейти в полностью запущенный статус. Сон при запуске, похоже, также спит при запуске службы. Через некоторое время время ожидания истекло, поэтому служба отображается как не запущенная, но сам процесс Windows удалось запустить. Должно быть лучшее решение. - person ; 22.06.2009
comment
Ну, поток занят - он спит. Чтобы уточнить: это НЕ код для OnStart! В OnStart вы должны создать новый поток с методом потока, который содержит приведенный выше код. - person Thorsten Dittmar; 22.06.2009