Compartilhar via


Change in System.ServiceProcess shutdown is coming in 3.5 RTM [Inbar Gazit]

In all current versions of the Framework we do not close the actual service when we get a shutdown request from the OS. Instead we just call OnShutdown and hope that the user has overridden this method and called Stop() themselves. We found out that many developers didn’t know they had to do that and this is a major issue when shutting down Vista laptops as it can add 10-20 seconds, for each managed service, to the time you have to wait before the machine is turned off.

To remedy the situation we decided to make a late-game change to the behavior of System.ServiceProcess.ServiceBase.  After we call OnShutdown we will check to see if the service is in the stopped state or not and if it’s not (meaning the developer did not call Stop() themselves) we will call Stop() on your behalf. This guarantees that the service would be stopped quickly when a shutdown operation is taking place to reduce delay and improve the experience of the customer. This was the recommended way to override OnShutdown before. If you have this code — you don’t have to make any changes. If you don’t have this code, you can pick up 3.5 RTM when it’s available to have this issue fixed.

class MyService : System.ServiceProcess.ServiceBase {

    protected override void OnShutdown() {

        // any shutdown-specific code not included in your OnStop method

        this.Stop();

    }

}

We will update the documentation to reflect this.

Please let us know if this change affects you in any unintended way.

Comments

  • Anonymous
    November 01, 2007
    I think you should do LOTS of testing and validating on this before putting the change out into the field. Unexpected changes in the way a service is shutdown could have lots of unintended consequences. Long-lived services can have lots of interactions with the surrounding system (i.e. outside the .NET sandbox), maintain complex state, and well-behaved services try to disentangle themselves so that the shutdown is graceful. Shutting down a service (really, any executable) is one of the most complicated chores the process must perform. A graceful shutdown could take a long time to complete, all of which is normal and acceptable, and which should be allowed to run to completion. Some services may establish their own watchdog and shutdown threads to handle this, and a completed shutdown may occur on a thread other than the one that invokes OnStop(). Existing services may not call Stop() from within OnStop() (mine doesn't) but ensures that the service exits through some other mechanism. In other words, IMO it is more important to ensure a service shuts down correctly than to shut down quickly. None of the documentation states that OnStop needs to call Stop, and in fact, what it does state seems to indicate that you do not need to call Stop.

  • Anonymous
    November 01, 2007
    It makes sense that the program would be expected to call Stop, but I checked the MSDN library for OnShutdown and there's no mention of it anywhere.  Did it just get left out?

  • Anonymous
    November 01, 2007
    > None of the documentation states that OnStop needs to call Stop, and in fact, what it does state seems to indicate that you do not need to call Stop. Who said anything about OnStop? You are suppose to call Stop in the OnShutDown method.

  • Anonymous
    November 01, 2007
    I did mistake one for the other, but here's what MSDN says for OnShutdown... "Use OnShutdown to specify the processing that occurs when the system shuts down. Often, OnShutdown will be similar to the processing in OnStop. This event occurs only when the operating system is shut down, not when the computer is turned off. OnShutdown is expected to be overridden when the CanShutdown property is true." It does not state that Stop should be called - it isn't surprising that no one knew they had to stop their own service. It also is not at all clear why there is a distinction between shutting down the operating system and turning off the computer - this implies that one can exit the Windows OS and leave the computer running. Perhaps this is a power management option, but the docs do a poor job of stating what it really means. I have not overriden this method in the past but I will do so from now on...I had assumed, apparently erroneously, that the OnStop method would get called when the service was being requested to shutdown regardless of why. It is not clear from the docs if OnStop gets called when the system is shutting down, and your statement implies that it does not. My earlier statement still stands about the need for verifying that existing services do not break.

  • Anonymous
    November 05, 2007
    What i think Inbar means when he say call stop is that you need to "stop your service" when receiving "OnShutdown". Do not expect OnStop to be called in this case.

  • Anonymous
    November 21, 2007
    Eeeek, had no idea you had to do this!  Could definitely do with some clarification in the MSDN docs.

  • Anonymous
    November 26, 2007
    I have a service written using ServiceBase and though I have set CanShutdown to true, OnShutdown is not called when the OS is shutdown. I'm currently testing against v2.0.50727. If you have an answer for this dilemma please post it here and on the following forum thread. http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1494724&SiteID=1 Thanks

  • Anonymous
    November 27, 2007
    OK, I (and some or all of the other posts I found) was(were) wrong.  OnShutdown is in fact being called.  However, the event log writes that I and others (including ServiceBase) used to record the shutdown notification and subsequent service Stop are failing (and throwing exceptions) because the Eventlog service is shutting down before my(their) service(s).  Marking my service as dependent on the Eventlog service does not change this behavior.  Presumably, I'm still missing some requirement to using the Eventlog in a meaningful manner, but if not then I guess I'll go re-event the rolling-log wheel again. Tested on Windows XP SP2 (detailed patch information unknown).