Как сделать так, чтобы служба Win работала в течение длительного времени с помощью Threading - PullRequest
3 голосов
/ 27 июля 2010

У меня есть выигрышный сервис, на котором размещены несколько рабочих процессов (WorkflowApplication и WorkflowServiceHost), которые мне нужно поддерживать в течение длительного времени. Поскольку OnStart () требует, чтобы он завершил работу и вернулся в ОС, у меня есть метод main, который запускается в другом потоке в пуле потоков. Мой Onstart () в основном выглядит так

protected override void OnStart(string[] args)
{
     eventLog.WriteEntry("Service starting...");
     ThreadPool.QueueUserWorkItem(new WaitCallback(ServiceMainThread));
     Thread.Sleep(100);
     eventLogCms.WriteEntry("Service Started.");
}

ServiceMainThread () - это метод, в котором выполняются мои рабочие процессы и реализуется основная функциональность. Когда я запускаю службу на моем компьютере с Windows 7, она запускается, а затем умирает примерно через 8 минут. На Win Server 2008 поток НИКОГДА не выполняется.

Так что я думаю, что я неправильно реализовал многопоточность, а то, что ServiceMainThread немного шатко. Я открыт для предложений о том, что можно улучшить, или в любом направлении, так как я новичок в потоках в .Net. Основной код потоков в ServiceMainThread кодируется так:

private void ServiceMainThread(object state)
{
    // .. execute workflows ..
    eventLog.WriteEntry("Workflows executed.");

    while(alive)
    {
        Thread.Sleep(1);
        // ... check workflow states and ensure they're still executing ...
    }

    // .. halt workflow executions and perform persist operations if necessary ..
    eventLog.WriteEntry("Workflows halted.");
}

А для наглядности приведу мою реализацию OnStop ():

protected override void OnStop()
{
    alive = false;
    this.haltEvent.WaitOne(); // haltEvent is of type ManualResetEvent 
}

Есть ли что-нибудь очевидное, что я мог бы изменить, чтобы мои рабочие процессы оставались в состоянии выполнения в течение длительного времени? Цикл while кажется слишком хакерским (не говоря уже о том, что мне не нравится задерживать поток на какое-то время), и я уверен, что может быть лучшее решение.

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

Обновление: Я получаю это исключение из .Net в журналах событий:

Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.NullReferenceException
Stack:
   at Ptm.ServiceMainThread()
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
   at System.Threading.ThreadHelper.ThreadStart()

Server 2008 является 64-разрядным, может ли это иметь какое-то отношение к моей проблеме?

Ответы [ 3 ]

4 голосов
/ 27 июля 2010

Во-первых, для продолжительного потока создайте свой собственный объект Thread и запустите его; не используйте ThreadPool. Пул потоков предназначен для небольших относительно коротких операций.

Во-вторых, есть несколько способов поддержать вашу нить. Самое основное - это то, что вы пробовали, это цикл while с вызовом в спящем режиме (или другой блокировкой) в конце. Это самое основное, хотя и не обязательно «лучшее». Существуют и другие параметры, такие как именованные WaitHandle объекты, к которым можно получить доступ из других приложений, которые могут обеспечить более детерминированное выполнение кода и меньше итераций wake-check-sleep.

Если, однако, вы либо не можете (или не хотите) изменять другие процессы для поддержки уведомления вашего сервиса о конкретных событиях, то то, что вы имеете, по сути, правильно. Тем не менее, я бы рекомендовал выбрать более разумное время; тебе действительно нужно проверять каждую миллисекунду?

2 голосов
/ 28 июля 2010

Я решил эту проблему с моей очень долго работающей службой Windows, заставив OnStart() запустить System.Timers.Timer и выполнить всю обработку в таймере ElapsedEventHandler.

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

Рабочие потоки обрабатывают все исключения, поэтому, если у кого-то возникает проблема, он регистрирует исключение, завершается и затем перезапускается при следующеминтервал таймера.Служебное ядро ​​никогда не падало.

0 голосов
/ 28 июля 2010

Что касается вашей блокировки, вам, вероятно, следует использовать парадигму ожидания / импульсного программирования для сигнализации о продолжении одного потока.Или просто присоединиться к теме.

Wait & Pulse - Threading в C #

...