如何阻止阻塞的win32线程?

Kir*_*ril 5 c++ concurrency winapi multithreading

我创建了一个自定义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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的想法是将相同数量的特殊任务排队(让我们称之为"终止任务"),因为池中有线程,每个"终止任务"都会调用_endthreadex(0)以退出线程.如果阻塞队列中还有其他任务,那么我真的不在乎,因为只要我将某个任务出列,我就会运行它并检查该_running标志以确定该线程是否需要将任何更多任务出列.

void TerminationTask::Run()
{
    _endthreadex(0);
}
Run Code Online (Sandbox Code Playgroud)

我对这种方法有几点顾虑; 主要是,如果我处理了一个非终止任务并且_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);
}
Run Code Online (Sandbox Code Playgroud)

这是否会导致与我的冲突TerminationTask或线程在执行后直接退出循环TerminationTask::Run()(即它不会调用_endthreadex(0)两次)?此外,还有比这更好的方法吗?

Dav*_*nan 6

_endthreadex(0)在线程方法结束时调用很好.它也是可选的.如果你只是正常地离开线程方法,那么_endthreadex(0)就会为你调用.

您可以显式调用_endthread或_endthreadex来终止线程; 但是,当线程从作为参数传递的例程返回到_beginthread或_beginthreadex时,会自动调用_endthread或_endthreadex.REF

发送终止任务是获取阻塞线程池线程以解除阻止和退出的正确方法.

所以,总结一下:

  1. 你的策略是好的,实施TerminationTask::Run是正确的.
  2. 你可以删除无害的呼叫到_endthreadex(0)最后ThreadPool::Loop.