C ++多线程:一次只保留一个线程(主线程以外的其他线程)

时间:2016-11-04 01:40:36

标签: c++ multithreading

我有一个执行一些繁重任务的函数,所以我想在主线程以外的线程中运行它。代码如下:

Data global_data;
void heavy_task() {
    ...//update global_data
}

void main() {
    while (True) {
        if (user_press_w) {
            std::thread t(heavy_task);
            t.detach();
        }
    }
}

如何修改代码,以便一次只运行一个线程?例如,如果用户按下启动线程的w,然后在第一个带有heavy_task的线程完成之前,则再次按下w,第一个线程将停止,第二个线程开始运行。这在用户持续按键的情况下也会有所帮助,在这种情况下,只有上次键检测触发的线程保持活动状态。

-----------------解决方案-------------------

我按照Adrian Colomitchi的建议修改了我的代码,

std::shared_ptr<std::thread> my_thread;
bool should_terminate = false;

Data global_data;
void heavy_task() {
    // This function actually does its work in a loop
    // so I check should_terminate at each iteration
    while (...) {
        ...
        if (should_terminate) return;
    }
}

void main() {
    while (True) {
        if (user_press_w) {
            should_terminate = true;
            if (my_thread!= nullptr && my_thread->joinable()) 
                my_thread->join();
            my_thread= std::make_shared<thread>(heavy_task);
            should_terminate = false;
        }
    }
}

---------------情况-------------------

我正在编写一个交互式光线追踪程序。世界首先由OpenGL应用程序绘制,用户在世界中导航以选择令人满意的视点并按下键以开始光线跟踪。在光线跟踪完成之前,用户可以更改视点并按下键以开始新的光线跟踪。我用glfw与操作系统交谈。

1 个答案:

答案 0 :(得分:1)

你需要让thread.detach()可中断:在做这些事情时,定期检查一个标志,该标志应该告诉它是继续还是丢弃所有内容并提前退出。

有了这个,当你收到另一个繁重任务的命令时,你首先引发“中断”标志,加入工作线程以确保它“死亡”(所以,没有{先前{1}}然后启动新的heavy_task

有些内容:

Data global_data;

void heavy_task(bool& shouldStop) {
    while(! ready && ! shouldStop) {
      // update **some** global data, in as small slices as you can afford
    }
}

void main() {
    bool interruptWThread=false;

    std::shared_ptr<std::thread> thread;

    while (True) {
        if (user_press_w) {
            if(thread) {
              interruptWThread=true;
              thread->join(); // wait here until thread exit is confirmed
              interruptWThread=false;
            }
            thread = std::make_shared<std::thread>(
              [& interruptWThread]->heavy_task(interruptWThread)
            );
            // nope!! Never detach a thread you may still need later
            // t.detach();
        }
    }
}