Topshelf - handling loops
Asked Answered
V

3

6

Generally with services, the task you want to complete is repeated, maybe in a loop or maybe a trigger or maybe something else.

I'm using Topshelf to complete a repeated task for me, specifically I'm using the Shelf'ing functionality.

The problem I'm having is how to handle the looping of the task.

When boot strapping the service in Topshelf, you pass it a class (in this case ScheduleQueueService) and indicate which is its Start method and it's Stop method:

Example:

    public class QueueBootstrapper : Bootstrapper<ScheduledQueueService>
{
    public void InitializeHostedService(IServiceConfigurator<ScheduledQueueService> cfg)
    {
        cfg.HowToBuildService(n => new ScheduledQueueService());
        cfg.SetServiceName("ScheduledQueueHandler");
        cfg.WhenStarted(s => s.StartService());
        cfg.WhenStopped(s => s.StopService());
    }
}

But in my StartService() method I am using a while loop to repeat the task I'm running, but when I attempt to stop the service through Windows services it fails to stop and I suspect its because the StartService() method never ended when it was originally called.

Example:

 public class ScheduledQueueService
{
    bool QueueRunning;

    public ScheduledQueueService()
    {
      QueueRunning = false;
     }


    public void StartService()
    {
        QueueRunning = true;

        while(QueueRunning){
                     //do some work
         }
    }

  public void StopService()     
  {
         QueueRunning = false;
  }
}

what is a better way of doing this?

  1. I've considered using the .NET System.Threading.Tasks to run the work in and then maybe closing the thread on StopService()

  2. Maybe using Quartz to repeat the task and then remove it.

Thoughts?

Venable answered 21/12, 2011 at 9:16 Comment(0)
R
3

Generally, how I would handle this is have a Timer event, that fires off a few moments after StartService() is called. At the end of the event, I would check for a stop flag (set in StopService()), if the flag (e.g. your QueueRunning) isn't there, then I would register a single event on the Timer to happen again in a few moments.

We do something pretty similar in Topshelf itself, when polling the file system: https://github.com/Topshelf/Topshelf/blob/v2_master/src/Topshelf/FileSystem/PollingFileSystemEventProducer.cs#L80

Now that uses the internal scheduler type instead of a Timer object, but generally it's the same thing. The fiber is basically which thread to process the event on.

If you have future questions, you are also welcomed to join the Topshelf mailing list. We try to be pretty responsive on there. http://groups.google.com/group/topshelf-discuss

Rosario answered 21/12, 2011 at 14:46 Comment(1)
the first link is brokenBrinkley
S
2

I was working on some similar code today I stumbled on https://mcmap.net/q/112218/-how-to-have-a-loop-in-a-windows-service-without-using-the-timer by accident and its been working like a charm for me.

Schizont answered 14/2, 2013 at 16:4 Comment(0)
S
0

I don't know about Topshelf specifically but when writing a standard windows service you want the start and stop events to complete as quickly as possible. If the start thread takes too long windows assumes that it has failed to start up, for example.

To get around this I generally use a System.Timers.Timer. This is set to call a startup method just once with a very short interval (so it runs almost immediately). This then does the bulk of the work.

In your case this could be your method that is looping. Then at the start of each loop check a global shutdown variable - if its true you quit the loop and then the program can stop.

You may need a bit more (or maybe even less) complexity than this depending on where exactly the error is but the general principle should be fine I hope.

Once again though I will disclaim that this knowledge is not based on topshelf, jsut general service development.

Sweetbrier answered 21/12, 2011 at 9:52 Comment(1)
After all these years, anyone know whether it is indeed also the case with Topshelf? There's no hint of that in the Topshelf documentation and I'm struggling to decide whether I should systematically spawn a new thread or something similar upon WhenStarted() in my service.Manley

© 2022 - 2024 — McMap. All rights reserved.