Служба Windows, использующая событие завершения работы, не может остановить службу
Я написал службу Windows, которая пытается читать сообщения из MSMQ и обрабатывать их. Я добавил установщик в свой проект и установил запуск вручную. Я устанавливаю службу, а затем запускаю ее с помощью инструмента "Службы". Затем я могу вернуться к своему проекту и присоединиться к процессу, чтобы пройти по коду.
Тем не менее, независимо от того, что я делаю, я не могу остановить службу ни в коде, ни из инструмента Сервисы. Я могу только думать, что это потому, что я использую класс ManualResetEvent для управления службой. Вот мой код Я пытаюсь проверить раздел Ошибка, так как в этот момент он должен выдать ошибку и остановить службу.
В моем классе обслуживания у меня есть:
private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;
public TestService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThread)
{
Name = "Test Messaging Reader Service Thread",
IsBackground = true
};
_thread.Start();
}
protected override void OnStop()
{
_shutdownEvent.Set();
if (!_thread.Join(3000))
{ // give the thread 3 seconds to stop
_thread.Abort();
}
IError logger = new Logger();
Exception ex = new Exception("The Test Messaging Service has been stopped.");
logger.Log(this, SeverityEnum.Warning, ex);
}
private void WorkerThread()
{
try
{
while (!_shutdownEvent.WaitOne(0))
{
TestMessageQueueReader processQueue = new TestMessageQueueReader();
processQueue.ReadFromQueue();
_shutdownEvent.Set();
_shutdownEvent.Reset();
}
}
catch (Exception)
{
_shutdownEvent.Set();
_shutdownEvent.Close();
}
}
Когда я перебираю код, он, как и ожидалось, попадает в исключение, и в этот момент я ожидаю, что смогу остановить службу.
1 ответ
Рабочий поток сбрасывает событие непосредственно перед его тестированием:
while (!_shutdownEvent.WaitOne(0))
{
// ...
_shutdownEvent.Reset();
}
Это означает, что если запрос на остановку не поступит точно в нужное время, он будет проигнорирован.
Вместо этого цикл должен выглядеть так:
while (!_shutdownEvent.WaitOne(0))
{
TestMessageQueueReader processQueue = new TestMessageQueueReader();
processQueue.ReadFromQueue();
}
Вы также не должны закрывать событие из рабочего потока, потому что оно может понадобиться другим потокам. (Событие будет автоматически закрыто при выходе из процесса, поэтому вам не нужно об этом беспокоиться.)
Что касается обработки исключений, вы не можете остановить службу, просто установив событие. Если существует более одного рабочего потока, установка события остановит их, но не саму службу. Я не совсем уверен, как заставить службу.NET останавливаться, но попробуйте вызвать ServiceBase.Stop.