Как правильно остановить многопоточный сервис окон.NET?

У Вас есть несколько вопросов там, большинству которых уже ответили люди ниже.

ответ на тот, который не был полностью обращен однако: да можно использовать сценарий/консоль для наблюдения, куда маршруты идут. Просто введите в app.[route_helper], и это ответит путем. Например app.users_path возвратится /users/

Так для Вашего типа app.entries_url в качестве примера для полного URL - или app.entries_path для его относительного пути в консоли.

24
задан Mark 7 October 2009 в 14:50
поделиться

5 ответов

Вызов для остановки службы возвращается, как только возвращается обратный вызов OnStop () . Судя по тому, что вы показали, ваш метод OnStop () мало что делает, что объясняет, почему он возвращается так быстро.

Есть несколько способов заставить вашу службу завершить работу.

Во-первых, вы можете переработать метод OnStop () , чтобы сигнализировать всем потокам о закрытии и ждать их закрытия перед выходом. Как предлагает @DSO, вы можете использовать для этого глобальный флаг bool (обязательно пометьте его как volatile ). Обычно я использую ManualResetEvent, но любой из них подойдет. Сообщите потокам о выходе. Затем присоединитесь к потокам с каким-то периодом ожидания (я обычно использую 3000 миллисекунд). Если к тому времени потоки еще не завершились, вы можете вызвать метод Abort () , чтобы выйти из них. Обычно метод Abort () не одобряется, но, учитывая, что ваш процесс все равно завершается, это не имеет большого значения. Если у вас постоянно есть поток, который необходимо прервать, вы можете переделать этот поток, чтобы он лучше реагировал на ваш сигнал о завершении работы.

Во-вторых, отметьте свои потоки как фоновые потоки (см. здесь подробнее). Похоже, вы используете класс System.Threading.Thread для потоков, которые по умолчанию являются потоками переднего плана. Это гарантирует, что потоки не задерживают завершение процесса. Это будет нормально работать, если вы выполняете только управляемый код. Если у вас есть поток, ожидающий неуправляемого кода, я

18
ответ дан 29 November 2019 в 00:04
поделиться

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

0
ответ дан 29 November 2019 в 00:04
поделиться

Чтобы ответить на первый вопрос (Почему будет ли служба продолжать работать более 30 секунд): есть много причин. Например, при использовании WCF остановка узла приводит к тому, что процесс перестает принимать входящие запросы, и он ожидает обработки всех текущих запросов перед остановкой.

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

Без дополнительной информации о том, что именно вы делаете, нет способ конкретно сказать вам, почему это занимает 30 секунд, но, вероятно, это тайм-аут.

Чтобы ответить на второй вопрос (почему возвращается контроллер службы): я не уверен. Я знаю, что в классе ServiceController есть метод WaitForState, который позволяет подождать, пока не будет достигнуто заданное состояние. Возможно, контроллер службы ожидает заданное время (еще один тайм-аут), а затем принудительно завершает работу вашего приложения.

Также очень возможно, что был вызван метод base.OnStop и метод OnStop вернулся, сигнализируя ServiceController о том, что процесс остановлен, хотя на самом деле есть некоторые потоки, которые еще не остановлены. вы несете ответственность за наименование этих потоков.

сигнализация ServiceController о том, что процесс остановлен, хотя на самом деле есть несколько потоков, которые не остановились. вы несете ответственность за наименование этих потоков.

сигнализация ServiceController о том, что процесс остановлен, хотя на самом деле есть несколько потоков, которые не остановились. вы несете ответственность за наименование этих потоков.

0
ответ дан 29 November 2019 в 00:04
поделиться

Диспетчер управления службами (SCM) вернется, когда вы вернетесь из OnStop. Поэтому вам нужно исправить свою реализацию OnStop, чтобы блокировать до тех пор, пока все потоки не завершатся.

Общий подход состоит в том, чтобы OnStop сигнализировал всем вашим потокам об остановке, а затем ждал их остановки. Чтобы избежать блокировки на неопределенный срок, вы можете дать потокам ограничение по времени для остановки, а затем прервать их, если они займут слишком много времени.

Вот что я делал в прошлом:

  1. Создайте глобальный флаг bool с именем Стоп, установите значение false, когда служба
  2. Когда вызывается метод OnStop, установите для флага Stop значение true, затем выполните Thread.Join для всех невыполненных рабочих потоков.
  3. Каждый рабочий поток отвечает за проверку флага Stop и корректно завершает работу, когда он правда. Эту проверку следует выполнять часто и всегда перед длительной операцией, чтобы избежать слишком долгой задержки завершения работы службы.
  4. В методе OnStop также есть тайм-аут для вызовов Join, чтобы дать потокам ограниченное время для правильного выхода ... после чего вы просто прерываете его.

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

11
ответ дан 29 November 2019 в 00:04
поделиться

Простой способ сделать это может выглядеть так:
-вначале крит глобальное событие

ManualResetEvent shutdownEvent;

-при запуске службы создать событие ручного сброса и установить его в исходное состояние без сигнала.
shutdownEvent = new ManualResetEvent(false);

-в событии остановки службы

shutdownEvent.Set();

не забудьте дождаться конца потоков
do
{
 //send message for Service Manager to get more time
 //control how long you wait for threads stop
}
while ( not_all_threads_stopped );

- каждый поток должен время от времени проверять событие, которое нужно остановить

if ( shutdownEvent.WaitOne(delay, true) ) break;
1
ответ дан 29 November 2019 в 00:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: