Quick (really) question about windows services.

According to the documentation, services require a minimum of 2 methods OnStart() and OnStop() to be useful.

OnStart() cannot contain the main execution code, it shouldn't loop, block or otherwise prevent the OnStart() method from returning quickly.

The Question:

If the above is true...it seems like, for a service to have any use at all, the OnStart() method MUST execute a different method on a different thread because running a method on the same thread from within the OnStart() method would cause blocking if that other method looped infinately...OnStart() would never return.

Is that correct?

Also, one other question for bonus points.

If a service implements OnCustomCommand(), you pass the custom command to the Service Controller and the Service Controller tells the service "Hey! do this command" and then ignores the service (doesn't wait for the service to do anything, it's just the messenger).

The question is, when the Service Controller does that, does the simple inclusion of the OnCustomCommand() method automatically listen for those commands? I guess what I mean is, if OnStart() starts a new thread (called ThreadA) and ThreadA runs in an infinite loop or blocks, while ThreadA is sitting there serving up whatever service it's supposed to and looping like there is no tomorrow, the OnStart() method that sprung ThreadA has ended which was on a different thread. Is that original (main) thread gone? Who is the Service Controller talking to? ThreadA? or does the controller instantiate an instance of OnCustomCommand() on a new thread called, say, ThreadB and just jump to the OnCustomCommand() method and skip the OnStart() method?

What happens if two commands are issued to the service controller in succession? Does the service controller wait for the first custom command to return before issuing the second one or does the service controller start yet another thread to process the new custom command?

I'm just a little confused about how the services communicate with the Service Controller and how custom commands are handled. If the service controller is going to start sprouting off a million new threads every time a custom command is issued...aren't you eventually going to run into potential deadlock situations, memory issues and/or CPU bottlenecking?

Could someone clarify this for me?

Yeah...so I lied...it wasn't a quick question. Sorry :)

As far a I know, the OnStart will be launched when you issue a Start of the service.

This will initialize the service and launch the main thread. You need to provide a mechanism to stop when the OnStop is launched. Normally an static boolean is enough to notify the stop order to the main thread.

The basic mechanism to permit the comunication between threads is to have some shared memory and an object to be locked by each thread before accessing those areas, then unlocked.

When you issue a custom command, this will notify the main thread what to do. So once more, you'll need a mechanism to communicate with the main thread.

Hope this helps.

Okay, so...where is the main thread at?

Looking at MSDN here it only mentions OnStart, OnPause, OnStop, OnContinue, OnShutdown, OnCustomCommand, OnPowerEvent...that's great...but what about the work or main method? I don't see it.

It does mention the Run method that is in the Main method, but looking here that Run method in the main method registers the service with the service controller and then the service controller executes the OnStart method and then what? Can I add my code under the call to Run()?

I'm so lost on how it actually works. Can the main method block or loop? Seems like a bad idea, wouldn't that render the service useless if the service controller tried talking to it or stopping it? It seems like from what I have read you have two choices when coding a service:

1. Create a timer and make your service execute a command on a set interval
2. Sprout off a thread (or threads) and run your code there.

Seems silly to me if those are the only options. I mean, a service that monitors a port or something for a connection request has to block (to be efficient it does anyway) and if that's the case, blocking a main thread seems like a terrible idea. At the very least 2 threads need to be used, one that blocks and one that listens to the service controller.

Am I missing something?

In OnStart you would start another thread that does the actual work for your service. In the documentation they mention using a timer to trigger an event to check if your service does something.

In OnStop you'll need some way to signal your thread to stop running (following the MSDN example, you'd stop the timer). Once you know the thread has stopped, you'd return from this method.

And no, the main method cannot block, it must start whatever threads, timers, etc. that your service needs then return to the caller. This will not affect your other threads, they will keep doing what they need to do. They also shouldn't block as that will make them difficult to stop if OnStop is called. If you are monitoring a port, you should timeout the checking for connection, check to see if you need to stop the thread, then check for a connection again. Use async connections and your service will be notified when a connection happens, you won't have to just sit and wait for it.

You don't need to 'listen' to the service controller. The service control calls the method it needs in your main service, thus giving that method a thread to run on.

Is a timer on the main thread necessary?

If I only start a thread in the OnStart() method, will the mere existence of the thread I started indicate that the service is running?

What happens if I leave OnStart empty and don't start a thread? Is it possible to just have the service sit idle until a custom command is issued that starts the work?

1) No, you don't have to use a timer, it's just an example.

2) Yes it will.

3) The service will start and stop immediately.