[英]How to stop a win32 thread that is blocking?
我创建了一个自定义ThreadPool
,它使用_beginthreadex()
启动了多个win32线程。 线程正在运行一个简单的循环,试图从阻塞队列中使任务出队,但是有时我需要停止线程,如果它们在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)
)? 此外,还有没有比这更好的方法了?
在线程方法末尾调用_endthreadex(0)
很好。 它也是可选的。 如果您只是正常退出线程方法,则会为您调用_endthreadex(0)
。
您可以显式调用_endthread或_endthreadex终止线程。 但是,当线程从作为参数传递给_beginthread或_beginthreadex的例程返回时,会自动调用_endthread或_endthreadex。 参考
发送终止任务是使阻塞的线程池线程解除阻塞并退出的正确方法。
因此,总结一下:
TerminationTask::Run
的实现是正确的。 ThreadPool::Loop
的末尾删除对_endthreadex(0)
的无害调用。 将终止任务放入队列中是正确的。 不过,我会尝试使用其他方法来处理它:
class TerminateThreadNow {};
void TerminationTask::Run()
{
throw TerminateThreadNow();
}
void ThreadPool::Loop()
{
while(_running)
{
try
{
// Attempts to dequeue a task and run it
_taskQueue.Dequeue()->Run();
}
catch(TerminateThreadNow&)
{
_running = false;
}
catch(BlockingQueueTerminate&)
{
// Eat the exception and check the running flag
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.