Выполните долгую инициализацию в службе Windows

Что лучший способ состоит в том, чтобы сделать некоторую долгую инициализацию, когда служба Windows запускает (или возобновляется от того, чтобы быть приостановленным), не блокируя Диспетчер управления службами?

5
задан Nick Meyer 17 June 2010 в 16:53
поделиться

5 ответов

Вы можете использовать BackgroundWorker для выполнения длительной операции в ответ на событие Service.Start.

Это достаточно просто сделать в методе OnStart () вашего класса, производного от ServiceBase . Также есть разумный хороший пример в MSDN .

protected override void OnStart(string[] args)
{
    var worker = new BackgroundWorker();
    worker.DoWork += DoSomeLongOperation;

    worker.RunWorkerAsync();
}

private void DoSomeLongOperation(object sender, DoWorkEventArgs e)
{
   // do your long operation...
}

Обратите внимание, что вы также можете подписаться на события ProgressChanged и RunWorkerCompleted , чтобы вы могли информировать диспетчер управления службами о своем прогрессе и успешном (или неудачном) запуске.

9
ответ дан 18 December 2019 в 14:42
поделиться

У меня тоже была эта проблема со службой Windows. Я думаю, вам нужно сохранить логику инициализации менее 30 секунд, иначе Windows Service Manager остановит службу.

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

Вы должны объявить таймер как параметр класса:

public partial class YourService: ServiceBase
{
   System.Timers.Timer tmrOnStart;

Затем инициализировать таймер в методе OnStart

protected override void OnStart(string[] args)
{
    //set the interval to 20 seconds
    tmrOnStart = new Timer();
    tmrOnStart.Interval = 20000;
    tmrOnStart.Enabled = true;
    tmrOnStart.AutoReset = false;
    tmrOnStart.Elapsed += new ElapsedEventHandler(tmrOnStart_Elapsed);
    tmrOnStart.Start();
}

Когда таймер вызовет событие Elapsed, он выполнит этот метод:

void tmrOnStart_Elapsed(object sender, ElapsedEventArgs e)
{
    heavyBusinessLogicMethod();
}

И вы должны нужно поместить вашу логику в метод heavyBusinessLogicMethod.

2
ответ дан 18 December 2019 в 14:42
поделиться

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

1
ответ дан 18 December 2019 в 14:42
поделиться

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

1
ответ дан 18 December 2019 в 14:42
поделиться

Лучший практический способ - создать рабочий поток.

Вообще существует другой документированный способ, который я могу объяснить на примере неуправляемого кода.Во время инициализации у службы Windows есть на это немного времени. На этот раз можно изменить где-нибудь в реестре. Если сервису требуется больше, можно вызвать

SetServiceStatus с dwCurrentState = SERVICE_START_PENDING , некоторые dwCheckPoint и dwWaitHint , из SERVICE_STATUS struct заполняется так, чтобы dwWaitHint было расчетным временем, требуемым для отложенной операции запуска в миллисекундах. Прежде чем истечет указанный промежуток времени, служба должна сделать свой следующий вызов функции SetServiceStatus либо с увеличенным значением dwCheckPoint , либо с изменением в dwCurrentState . См. Описание dwWaitHint на http://msdn.microsoft.com/en-us/library/ms685996 (VS.85) .aspx .

0
ответ дан 18 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: