Как лучше всего сигнализировать потокам, которые спят или блокируются, чтобы остановиться? - PullRequest
2 голосов
/ 26 сентября 2010

У меня есть сервис, который мне нужно закрыть и обновить.У меня проблемы с этим в двух разных случаях:

  1. У меня есть несколько потоков, которые спят в течение большого количества времени.Очевидно, я не могу дождаться, когда они проснутся, чтобы закончить работу службы.У меня была мысль использовать AutoResetEvent, который устанавливается некоторым потоком контроллера, когда интервал ожидания увеличен (просто проверяя каждые две секунды или что-то в этом роде), и запускать его немедленно во время OnClose.Есть ли лучший способ облегчить это?

  2. У меня есть один поток, который вызывает вызов метода блокировки (тот, который я не могу изменить).Как вы сигнализируете такой нить, чтобы остановить?

Ответы [ 3 ]

3 голосов
/ 26 сентября 2010
  1. Я не уверен, правильно ли я понял ваш первый вопрос, но рассматривали ли вы использование WaitForSingleObject в качестве альтернативы Sleep?Вы можете указать время ожидания, а также объект для ожидания, поэтому, если вы хотите, чтобы он проснулся раньше, просто подайте сигнал объекту.

  2. Что именно вы подразумеваете под "вызовомблокирующая тема "?Или вы просто имели в виду блокирующий звонок?В общем, нет способа прервать поток без принудительного его завершения.Однако, если вызов является системным вызовом, может иметь возможность вернуть управление, сделав вызов неудачным, например.отмена ввода / вывода или закрытие связанного дескриптора.

2 голосов
/ 26 сентября 2010

Для 1. Вы можете перевести свои потоки в прерывистый сон, используя SleepEx вместо Sleep. Как только они получат этот сигнал отключения (инициируемый из вашей логики завершения с помощью QueueUserApc ), вы можете обнаружить это, используя код возврата из SleepEx, и соответствующим образом завершить эти потоки. Это похоже на предложение использовать WaitForSingleObject, но вам не нужен другой дескриптор для каждого потока, который просто используется для завершения связанного потока.

Возвращаемое значение равно нулю, если указанный интервал времени истек.

Возвращаемое значение WAIT_IO_COMPLETION если функция вернулась из-за одного или больше обратного вызова завершения ввода / вывода функции. Это может произойти только если bAlertable ИСТИНА, и если поток который вызвал функцию SleepEx та же самая нить, которая называется расширенная функция ввода / вывода.

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

1 голос
/ 26 сентября 2010

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

Кроме того, вы можете реализовать решение, которое обычно делают сами ОС: один предупреждающий сигнал с просьбой очистить процесс как можно лучше (который устанавливает флаг и корректно завершает то, что может быть изящно остановлено), а затем принудительное завершение, если процесс не выходит сам по себе (что прекращает такие неприятные вещи, как блокировка ввода / вывода).

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

О, и одно последнее предупреждение; Службы Windows могут совместно использовать процесс (я полагаю, что для эффективности, хотя это кажется мне оптимизмом, которого можно избежать), поэтому, если вы идете по этому пути, вы хотите убедиться, что ваша служба не делится процессом с другими службами , Вы можете убедиться в этом, передав параметр SERVICE_WIN32_OWN_PROCESS в ChangeServiceConfig .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...