Новый поток должен быть создан на ServiceMain?
MSDN говорит, что:
"Функция ServiceMain должна создать глобальное событие, вызвать функцию RegisterWaitForSingleObject для этого события и завершить работу. Это прервет поток, в котором выполняется функция ServiceMain, но не прекратит работу службы..."
Итак, вопрос таков: должен быть создан новый поток внутри функции ServiceMain для выполнения кода службы, или я могу просто установить службу в состояние RUNNING и использовать поток ServiceMain для запуска кода службы? Если поток ServiceMain используется для запуска сервисного кода, SCM останется заблокированным, даже если для состояния сервиса установлено значение RUNNING?
2 ответа
Я не думаю, что способ реализации услуг, описанный в этом заявлении MSDN, является единственно возможным. Это противоречило бы примеру службы MSDN по адресу http://msdn.microsoft.com/en-us/library/windows/desktop/bb540476(v=vs.85).aspx. В этом примере служба ожидает события в том же потоке, который вызвал ServiceMain. Этот способ, вероятно, лучше подходит для простых сервисов, которые прекрасно работают с одним потоком.
Если вы решите использовать RegisterWaitForSingleObject, вам не нужно явно создавать потоки. Страница MSDN для RegisterWaitForSingleObject гласит: "Новые потоки ожидания создаются автоматически при необходимости". Вы должны открыть каналы ввода-вывода, которые будут обслуживать ваши службы, и привязать их дескрипторы к пулу потоков перед выходом из ServiceMain.
MSDN говорит: "Диспетчер управления службами (SCM) ожидает, пока служба не сообщит о состоянии SERVICE_RUNNING
, Рекомендуется, чтобы служба сообщала об этом состоянии как можно быстрее, так как другие компоненты системы, которые требуют взаимодействия с SCM, будут заблокированы в течение этого времени ".
Диспетчер управления создает новый поток для выполнения функции ServiceMain для службы. Функция ServiceMain должна выполнять следующие задачи.
5. Выполните служебные задачи или, если нет ожидающих выполнения задач, верните управление вызывающей стороне. Любое изменение в состоянии обслуживания требует вызова
SetServiceStatus
сообщить новую информацию о статусе.
Из этого примера следует, что вы можете выполнять более сложные задачи инициализации внутри функции ServiceMain, такие как создание дополнительных потоков.
Руководство по созданию многопоточных сервисов.