Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perform lengthy initialization in Windows Service

What's the best way to do some lengthy initialization when a Windows service starts up (or resumes from being paused) without blocking the Service Control Manager?

like image 722
Nick Meyer Avatar asked Jun 17 '10 16:06

Nick Meyer


3 Answers

You can use a BackgroundWorker to perform your lengthy operation in response to the Service.Start event.

It's easy enough to do so in the OnStart() method of your ServiceBase-derived class. There's also a reasonable good example on 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...
}

Note that you can also subscribe to the ProgressChanged and RunWorkerCompleted events, so that you can inform the service control manager of your progress and startup success (or failure).

like image 154
LBushkin Avatar answered Sep 18 '22 23:09

LBushkin


I also had this problem with a Windows Service. I think you have to keep the initialization logic under 30 seconds, otherwise the Windows Service Manager will stop the service.

What I did was quite simple. I created a method where I put all of the heavy logic that needed to be executed and then I created a timer that would tick after 20 seconds and execute that method. So the service would start, then create the timer, initialize it with an interval of 20 seconds and then finish the initialization. After 20 seconds the timer would tick and start the business logic of the application. Of course you can specify whatever interval of time you want.

You should declare the timer as a parameter of the class:

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

Then initialize the timer in the OnStart method

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();
}

When the timer will trigger the Elapsed event, it will execute this method:

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

And you would have to put your logic in the heavyBusinessLogicMethod method.

like image 24
Alex Avatar answered Sep 21 '22 23:09

Alex


I have to do this as well: I spawn a thread on startup that does all of its initialization and sets a private 'isInitialized' to true when it's finished. The service does actions periodically (ie, on a timer) and won't begin those actions if isInitialized isn't set to true.

like image 27
Steven Evers Avatar answered Sep 18 '22 23:09

Steven Evers