Верхняя полка - петли - PullRequest
       15

Верхняя полка - петли

6 голосов
/ 21 декабря 2011

Обычно со службами задача, которую вы хотите выполнить, повторяется, возможно, в цикле или, может быть, в триггере или, может быть, в другом месте.

Я использую Верхняя полка , чтобы выполнить для меня повторное задание, в частности, я использую функциональность Полки.

Проблема, с которой я столкнулся, заключается в том, как справиться с зацикливанием задачи.

При загрузке связывая сервис в Topshelf, вы передаете ему класс (в данном случае ScheduleQueueService) и указываете, какой это метод Start, а метод Stop:

Пример:

    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());
    }
}

Но в моем методе StartService() я использую цикл while, чтобы повторить задачу, которую я запускаю, но когда я пытаюсь остановить службу через службы Windows, она не может остановиться, и я подозреваю, что это потому, что метод StartService() никогда не заканчивался, когда он первоначально назывался.

Пример: * * один тысяча двадцать-одна

 public class ScheduledQueueService
{
    bool QueueRunning;

    public ScheduledQueueService()
    {
      QueueRunning = false;
     }


    public void StartService()
    {
        QueueRunning = true;

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

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

как лучше это сделать?

  1. Я рассмотрел использование .NET System.Threading.Tasks для запуска работы, а затем, возможно, закрыл поток в StopService ()

  2. Может быть, использовать Кварц , чтобы повторить задание, а затем удалить его.

Мысли

Ответы [ 3 ]

3 голосов
/ 21 декабря 2011

Обычно, как бы я справился с этим, есть событие Timer, которое срабатывает через несколько мгновений после вызова StartService().В конце события я бы проверил флаг stop (установленный в StopService()), если флаг (например, ваш QueueRunning) отсутствует, тогда я бы зарегистрировал одно событие на таймере, чтобыповториться через несколько минут.

Мы делаем нечто очень похожее в самом Topshelf при опросе файловой системы: https://github.com/Topshelf/Topshelf/blob/v2_master/src/Topshelf/FileSystem/PollingFileSystemEventProducer.cs#L80

Теперь используется тип внутреннего планировщика вместо объекта Timer, но, как правило, это то же самоевещь.fiber - это, в основном, поток для обработки события.

Если у вас есть вопросы в будущем, вы также можете присоединиться к списку рассылки Topshelf.Мы стараемся быть там отзывчивыми.http://groups.google.com/group/topshelf-discuss

2 голосов
/ 14 февраля 2013

Сегодня я работал над некоторым подобным кодом, я случайно наткнулся на https://stackoverflow.com/a/2033431/981, и он работал для меня как обаяние.

0 голосов
/ 21 декабря 2011

Я не знаю конкретно о Topshelf, но при написании стандартной службы Windows вы хотите, чтобы события start и stop завершались как можно быстрее.Если запуск потока занимает слишком много времени, Windows предполагает, что он не запустился, например.

Чтобы обойти это, я обычно использую System.Timers.Timer.Он настроен на вызов метода запуска только один раз с очень коротким интервалом (поэтому он запускается практически сразу).Это делает большую часть работы.

В вашем случае это может быть ваш метод, который зацикливается.Затем в начале каждого цикла проверяйте глобальную переменную завершения работы. Если это правда, вы выходите из цикла, а затем программа может остановиться.

Возможно, вам потребуется немного больше (или, может быть, даже меньше) сложности, чем это, в зависимости отгде именно ошибка, но общий принцип должен быть в порядке, я надеюсь.

Еще раз, хотя я откажусь от того, что эти знания не основаны на верхней полке, а только развивают общее обслуживание.

...