В вашем примере PerformHealthCheck()
будет работать неопределенно долго. Таким образом, ваш OnStart
никогда не заканчивается. Не знаю, только ли это из-за вашего упрощенного примера.
Однако, вы что-то регистрируете, когда это происходит? Например, зарегистрируйте конец метода OnStart и убедитесь, что при возникновении проблемы OnStart фактически завершился. В своем коде-комментарии вы пишете //Code is not reachabl..
, вы тоже что-то там регистрируете? Или в замке?
Кстати, блокировка запуска и остановки может показаться хорошей идеей для синхронизации, но как пользователь, если я хочу остановить службу, я действительно хочу ее остановить. Независимо от того, все еще в состоянии запуска. На самом деле, если служба не отвечает на команду остановки, я подозреваю, что в 90% случаев диспетчер задач в любом случае является следующей остановкой ... Разве не лучше, если вы попытаетесь переписать логику останова таким образом, чтобы он всегда просто выполняет и ломает все, что может? Это, вероятно, решит вашу проблему, а также улучшит опыт imo.
Редактировать, кажется, что блокировки на самом деле ничего не делают (по крайней мере, если они используются только здесь, а не для блокировки чего-либо в другом месте) ОС не будет передавать команду OnStop, если она все еще StartPending .. :
Возможно ли, что это происходит, когда запуск просто занимает LONG и остановка вызывается до того, как запуск завершится? Смотрите этот пример:
class logger
{
static readonly object _logSync = new object();
public void Log(string message)
{
var m = $"{DateTime.Now.ToString("HH:mm:ss")}; {message}{Environment.NewLine}";
lock(_logSync)
{
File.AppendAllText(@"C:\temp\test.txt", m);
}
}
}
class Program
{
static void Main(string[] args)
{
ServiceBase.Run(new TestHangService());
}
}
class TestHangService : ServiceBase
{
private logger _log;
public TestHangService()
{
_log = new logger();
}
protected override void OnStart(string[] args)
{
_log.Log("OnStart");
Thread.Sleep(30 * 1000);
_log.Log("OnStart exit");
}
protected override void OnStop()
{
_log.Log("OnStop");
}
}
Тогда
C:\WINDOWS\system32>sc create DeleteMe binpath="C:\testprojects\TestService\TestService\bin\Debug\TestService.exe"
[SC] CreateService SUCCESS
C:\WINDOWS\system32>sc start deleteMe
SERVICE_NAME: deleteMe
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(NOT_STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x7d0
PID : 27376
FLAGS :
C:\WINDOWS\system32>echo "executed directly after starting"
"executed directly after starting"
C:\WINDOWS\system32>sc stop deleteMe
SERVICE_NAME: deleteMe
TYPE : 10 WIN32_OWN_PROCESS
STATE : 2 START_PENDING
(STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
C:\WINDOWS\system32>echo "waiting for 30 sec"
"waiting for 30 sec"
C:\WINDOWS\system32>sc stop deleteMe
[SC] ControlService FAILED 1061:
The service cannot accept control messages at this time.
который регистрирует:
18: 32: 20; OnStart
18: 32: 50; Выход при запуске
примечание не остановлено
Кажется, это не восстановится (что удивило меня) даже через 10 минут:
C:\WINDOWS\system32>sc query deleteme
SERVICE_NAME: deleteme
TYPE : 10 WIN32_OWN_PROCESS
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
CHECKPOINT : 0x0
WAIT_HINT : 0x0
C:\WINDOWS\system32>sc stop deleteme
[SC] ControlService FAILED 1061:
The service cannot accept control messages at this time.