Я создал пользовательский ThreadPool
, который запускает несколько потоков win32 с _beginthreadex()
.Потоки выполняют простой цикл, который пытается удалить задачи из очереди блокировки, но иногда мне нужно остановить потоки, и если они заблокированы на Dequeue
, тогда я не знаю, как вывести потоки из этой блокировкиstate.
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)
дважды)?Кроме того, есть ли лучший подход, чем этот?