Почему метод Stop вызывается много раз в Topshelf - PullRequest
0 голосов
/ 17 декабря 2018

Topshelf работает как брокер службы Windows в нашем приложении.Этим утром мы обнаруживаем, что метод Stop вызывается много раз.Вот соответствующий код.

class Program
{
    static void Main(string[] args)
    {
        ILog Log = new FileLog();
        try
        {
            HostFactory.Run(serviceConfig =>
            {
                serviceConfig.Service<ServiceManager>(serviceInstance =>
                {
                    serviceInstance.ConstructUsing(() => new ServiceManager());
                    serviceInstance.WhenStarted(execute => execute.Start());
                    serviceInstance.WhenStopped(execute => execute.Stop());
                });

            });
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            Log.Error("Program.Main", ex, LogType.Error);
            Console.ReadLine();
        };
    }
}

В ServiceManager у нас есть метод Stop, который будет вызван, после чего TopShelf получит сигнал остановки из операционной системы.

class ServiceManager
{

    xxx.....

    public bool Stop()
    {
        try
        {
            _log.Info("The service is stopping", LogType.Info);
            _service.StopExecuteProduceMessage();
            Task.WaitAll(_tasks.ToArray());
            _log.Info("The service is stopped", LogType.Info);
        }
        catch (Exception ex)
        {
            _log.Error("Stop", ex, LogType.Error);
        }
        return true;
    }
}

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

enter image description here

Я предполагаю, что Topshelf вызывает метод ServiceManager.Stop много раз.Кто-нибудь сталкивался с этой проблемой раньше?Я хочу знать, что могу проследить, почему это происходит.

Кто-нибудь может помочь?Большое спасибо.

1 Ответ

0 голосов
/ 17 декабря 2018

Вы испытываете это поведение, потому что ваш метод Stop () занимает некоторое время, но не отвечает на запрос на остановку.

Ваш метод по сути выглядит так:

Stop() {
   log-stopping;
   wait-a-while;
   log-stopped;
}

Пока вы ждете, статус сервиса остается «Работает».Это приводит к тому, что инициатор запроса (может быть сама Windows или другая программа) продолжает повторную отправку запроса на остановку, что приводит к множественным параллельным / перекрывающимся вызовам Stop ().Это учитывает первые 10 строк в журнале, который вы включили.

Вы видите, что для завершения «ожидания» требуется почти 20 секунд (с 05:39:45 до 05:40:04).

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

Чтобы устранить проблему, вам необходимо:

  1. Измените свой вызов WhenStopped () для передачи параметра HostControl в Stop ():

    serviceInstance.WhenStopped ((execute, hostControl) => execute.Stop (hostControl));

  2. Обновите метод Stop (), чтобы он принял параметр HostControl и сделал этот вызов перед вызовом Task.WaitAll ():

    hostControl.RequestAdditionalTime (TimeSpan.FromSeconds (30));

Это сообщит Windows, что ваша служба получила запрос и может работать над ним до 30 секунд.Это должно избежать повторных вызовов.

Ссылка: Документация верхнего полка

...