Выполните длительную инициализацию в Windows Service - PullRequest
5 голосов
/ 17 июня 2010

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

Ответы [ 5 ]

9 голосов
/ 17 июня 2010

Вы можете использовать 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, чтобы вы могли сообщить об этом менеджеру управления службами.вашего прогресса и успеха запуска (или неудачи).

2 голосов
/ 18 июня 2010

У меня также была эта проблема со службой 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.

1 голос
/ 17 июня 2010

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

1 голос
/ 17 июня 2010

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

0 голосов
/ 17 июня 2010

Лучший прагматичный способ - создать рабочий поток.

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

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

...