Я создал собственный ThreadPool
, который запускает несколько потоков win32 с помощью _beginthreadex ()
. Потоки выполняют простой цикл, который пытается удалить задачи из очереди блокировки, но иногда мне нужно остановить потоки, и если они заблокированы на Dequeue
, я не знаю, как получить потоки из этого состояния блокировки.
void ThreadPool::Loop()
{
while(_running)
{
try
{
// Attempts to dequeue a task and run it
_taskQueue.Dequeue()->Run();
}
catch(BlockingQueueTerminate&)
{
// Eat the exception and check the running flag
continue;
}
}
}
Моя идея заключалась в том, чтобы поставить в очередь такое же количество специальных задач (назовем их «задачами завершения»), сколько потоков в пуле, и каждая «задача завершения» будет вызывать _endthreadex (0)
по порядку чтобы выйти из потока. Если в очереди блокировки есть другие задачи, то мне все равно, потому что, как только я удалю задачу из очереди, я ее запускаю и проверю флаг _running
, чтобы определить, нужно ли потоку исключить из очереди еще какие-либо задачи.
void TerminationTask::Run()
{
_endthreadex(0);
}
У меня есть несколько опасений по поводу этого подхода; в основном, если я обработал непрерывающуюся задачу и для флага _running
установлено значение false
, то мой поток не будет вызывать _endthreadex (0)
при выходе петля.Мне было интересно, могу ли я вызвать _endthreadex (0)
в конце цикла следующим образом:
void ThreadPool::Loop()
{
while(_running)
{
try
{
// Attempts to dequeue a task and run it
_taskQueue.Dequeue()->Run();
}
catch(BlockingQueueTerminate&)
{
// Eat the exception and check the running flag
continue;
}
}
_endthreadex(0);
}
Это вызовет конфликт с моей TerminationTask
или поток выйдет из цикла непосредственно после выполнения TerminationTask :: Run ()
(т.е. он не будет вызывать _endthreadex (0)
дважды)? Кроме того, есть ли лучший подход, чем этот?