Блокировка двух потоков в службе Windows C ++

У меня есть служба Windows, написанная на C ++, которая функционирует как TCP-сервер, прослушивающий входящие соединения.

Я инициализировал сокет сервера и поставил accept Код в отдельном потоке. Это примет и обработает входящие соединения.

Однако мне также нужно остановить этот поток в случае, если служба получает сигнал STOP. Поэтому я подумал о создании объекта события, используя CreateEvent и ждет, пока это будет сигнализировано. Это ожидание будет происходить в потоке, который создает поток принятия. Так что я мог бы использовать TerminateThread функция для остановки потока приема при получении сигнала STOP.

Тем не мение, MSDN Говорит, что

TerminateThread — опасная функция, которую следует использовать только в самых крайних случаях.

Насколько строго следует этому следовать, и правильный ли мой подход? Что может быть еще один способ сделать это?

2

Решение

В Windows вы можете разбудить блокировку accept звонить из другого потока просто позвонив closesocket, Блокировка accept call вернет -1, и ваш код сможет выйти из цикла, в котором он находится, проверив некоторые другие условия выхода, которые вы уже установили (например, глобальная переменная)

Это также работает с Mac (и, вероятно, производными BSD) с close функция, но не Linux. Более универсальное решение этой проблемы в UNIX Вот.

Некоторые псевдо-код для решения Windows ниже.

SOCKET _listenSocket;
bool _needToExit = false;
HANDLE _hThread;

void MakeListenThreadExit()
{
_needToExit = true;
closesocket(_listenSocket);
_listenSocket = INVALID_SOCKET;

// wait for the thread to exit
WaitForSingleObject(_hThread, INFINITE);
}

DWORD __stdcall ListenThread(void* context)
{
while (_needToExit == false)
{
SOCKET client = accept(_listenSocket, (sockaddr*)&addr, &addrSize);
if ((client == -1) || _needToExit)
{
break;
}
ProcessClient(client);
}
return 0;
}
2

Другие решения

В этой ситуации не используйте accept() на розетке блокировки. Вместо этого используйте неблокирующий сокет. Тогда вы можете использовать select() с таймаутом, чтобы ваша нить могла периодически проверять условие завершения. Или лучше использовать WSACreateEvent() с WSASelectEvent(), Создайте два объекта события, один для обнаружения клиентских подключений и один для обнаружения завершения потока. Вы можете использовать WSAWaitForMultipleEvents() ждать обоих событий одновременно. использование WSASetEvent() сообщить о событии завершения при необходимости и вызвать accept() или же WSAAccept() всякий раз, когда другое событие сигнализируется. WSAWaitForMultipleEvents() скажет вам, на каком событии действовать.

1

По вопросам рекламы [email protected]