user1270384
user1270384

Reputation: 721

Windows service OnStop issue

I have a Windows service which I put together from a number of blogs and forums, mainly questions I've asked and had answered here. The service works fine. The only problem is when I stop the service; pasted further down is what I see in the log files when I stop it.

public partial class GBBInvService : ServiceBase
{
    private static readonly ILog log = LogManager.GetLogger(typeof(GBBInvService));
    System.Timers.Timer timer = new System.Timers.Timer();
    private volatile bool _requestStop=false;
    private ManualResetEventSlim resetEvent = new ManualResetEventSlim(false);


    public GBBInvService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        _requestStop = false;
        timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        timer.Interval = 18000;
        timer.Enabled = true;
        timer.Start();
        log.Info("GBBInvService Service Started");
    }

    protected override void OnStop()
    {
        log.Info("inside stop"); 
        if (!_requestStop)
        {
            log.Info("Stop not requested");
            timer.Start();
        }    
        else
        {
            log.Info("On Stop Called");
            WaitUntilProcessCompleted();
        }
    }

    private void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        log.Info("Timer elapsed at " + Convert.ToString(e.SignalTime)); 
        InvProcessing();
    }

    private void InvProcessing()
    {
        try
        {
            resetEvent.Reset();
           //*Processing here*
        }
        catch (Exception ex)
        {
            resetEvent.Set();
            log.Error(ex.Message); 
        }
    }


    private void WaitUntilProcessCompleted()
    {
        resetEvent.Wait();
    }
}

The service stops properly and starts again fine, but I don't know if my code is wrong because the log file is showing:

2013-04-23 14:53:01,062 [6] INFO GBBInvService.GBBInventoryService [(null)] – inside stop

2013-04-23 14:53:01,062 [6] INFO GBBInvService.GBBInventoryService [(null)] – Stop not requested

It's going inside of (!_requestStop) instead of the else. Is my code wrong? Would somebody be able to explain to me why it is going inside of (!_requestStop) instead of the else statement.

Any advise would be greatly appreciated, as I've only just started getting a hands-on of Windows services and most recently logging.

Upvotes: 0

Views: 5608

Answers (3)

J0e3gan
J0e3gan

Reputation: 8938

Based on the code you have shared, I think there are a few things going on:

  • As others have pointed out, without _requestStop = true; somewhere, !_requestStop will always evaluate to true. There is no possibility then that the else in OnStop() will execute. With volatile added to _requestStop's declaration, maybe you expected the OS to modify it, but the declaration should then be public; and even then the OS is not going to automagically modify _requestStop. So, yes, with respect to _requestStop and expecting the else to ever execute, your code seems wrong.
  • Your use of _requestStop seems to betray mistrust that OnStop() will only be called when it should be called (i.e. when a stop has been requested). Being new to Windows services, I guess I could see that, but such mistrust is unwarranted.
  • Being new to logging as you point out, you are over-logging IMO; sometimes less is more.

Unless code you have not shared uses _requestStop, here are the changes I would suggest for the specific issue and questions you raised about your code:

public partial class GBBInvService : ServiceBase
{
    private static readonly ILog log = LogManager.GetLogger(typeof(GBBInvService));
    System.Timers.Timer timer = new System.Timers.Timer();
    //private volatile bool _requestStop=false; // no _requestStop
    private ManualResetEventSlim resetEvent = new ManualResetEventSlim(false);


    public GBBInvService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        //_requestStop = false;
        timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
        timer.Interval = 18000;
        timer.Enabled = true;
        timer.Start();
        log.Info("GBBInvService Service Started");
    }

    protected override void OnStop()
    {
        //log.Info("inside stop"); 
        //if (!_requestStop)
        //{
        //    log.Info("Stop not requested");
        //    timer.Start();
        //}    
        //else
        //{
        //    log.Info("On Stop Called");
        //    WaitUntilProcessCompleted();
        //}

        WaitUntilProcessingCompleted();
        log.Info("GBBInvService Service Stopped");
    }

    private void timer_Elapsed(object sender, ElapsedEventArgs e)
    {
        log.Info("Timer elapsed at " + Convert.ToString(e.SignalTime)); 
        InvProcessing();
    }

    private void InvProcessing()
    {
        try
        {
            resetEvent.Reset();
            //*Processing here*

        }
        catch (Exception ex)
        {
            log.Error(ex.Message); 
        }
        finally
        {
            resetEvent.Set();
        }
    }


    private void WaitUntilProcessCompleted()
    {
        resetEvent.Wait();
    }
}

Upvotes: 2

nathas
nathas

Reputation: 949

Unless something changes _requestStop, it will always be false.

ServiceBase has no code that will automagically set _requestStop to true, and your program doesn't change it any where.

Your code is running as expected.

OnStop() is ran when a stop is REQUEST from the Windows Service Manager. See more at http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase.onstop.aspx

You would set

_requestStop = true 

at the top of OnStop() to signal to the rest of the program to finish any tasks.

That said, I don't know what you want this program to do. I can advise further with more details as to what it's supposed to be doing.

Upvotes: 7

Kelmen
Kelmen

Reputation: 1063

i don't see what's wrong. your logic never change _requestStop = true. it's always false.

!false definitely will go through if-true block.

Upvotes: 1

Related Questions