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?
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).
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With