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

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

Я использую Topshelf для выполнения повторяющейся задачи, в частности, я использую функцию Shelf'ing.

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

При загрузке службы в 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. Возможно, используя Quartz, чтобы повторить задачу, а затем удалить ее.

Мысли?


person Mike    schedule 21.12.2011    source источник


Ответы (3)


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

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

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

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

person Travis    schedule 21.12.2011
comment
первая ссылка битая - person SteveC; 15.07.2015

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

person David Negron    schedule 14.02.2013

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

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

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

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

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

person Chris    schedule 21.12.2011
comment
После всех этих лет кто-нибудь знает, действительно ли то же самое и с Topshelf? В документации Topshelf нет намека на это, и я изо всех сил пытаюсь решить, должен ли я систематически создавать новый поток или что-то подобное в WhenStarted() в моей службе. - person guillaume31; 12.09.2016