【问题标题】:How to stop the thread execution in C++如何在 C++ 中停止线程执行
【发布时间】:2019-04-24 07:39:22
【问题描述】:

我在主程序中创建了一个线程,一旦主程序终止,线程执行就必须停止。我正在使用reader.join(); 来终止线程执行。但它并没有停止执行。

我尝试使用下面提到的代码,我正在使用thread.join(); 函数,但它无法终止线程。在主程序之后,我的线程也在继续执行。

#include <algorithm>
#include <array>
#include <atomic>
#include <mutex>
#include <queue>
#include <cstdint>
#include <thread>
#include <vector>

using namespace std;
using namespace std::chrono;

typedef pair<int, Mat> pairImage;

class PairComp {
public:
    bool operator()(const pairImage& n1, const pairImage& n2) const
    {
        if (n1.first == n2.first)
            return n1.first > n2.first;
        return n1.first > n2.first;
    }
};

int main(int argc, char* argv[])
{
    mutex mtxQueueInput;
    queue<pairImage> queueInput;
    int total = 0;
    atomic<bool> bReading(true);
    thread reader([&]() {
        int idxInputImage = 0;
        while (true) {
            Mat img = imread("img_folder/");
            mtxQueueInput.lock();
            queueInput.push(make_pair(idxInputImage++, img));
            if (queueInput.size() >= 100) {
                mtxQueueInput.unlock();
                cout << "[Warning]input queue size is " << queueInput.size();
                // Sleep for a moment
                sleep(2);
            }
            else {
                mtxQueueInput.unlock();
            }
        }
        bReading.store(false);
    });

    while (true) {
        pair<int, Mat> pairIndexImage;
        mtxQueueInput.lock();
        if (queueInput.empty()) {
            mtxQueueInput.unlock();
            if (bReading.load())
                continue;
            else
                break;
        }
        else {
            // Get an image from input queue
            pairIndexImage = queueInput.front();
            queueInput.pop();
        }
        mtxQueueInput.unlock();
        cv::Mat frame = pairIndexImage.second;

        cv::rectangle(frame, cv::Rect{ 100, 100, 100, 100 }, 0xff);
    }

    cv::imshow("out_image", frame);
    waitKey(1);

    if (total++ == 200)
        break;

    if (reader.joinable()) {
        reader.join();
    }

    return 0;
}

【问题讨论】:

  • 为了改善您的问题,您可以缩短代码示例以使其更具可读性 =)

标签: c++ multithreading c++11 pthreads mutex


【解决方案1】:

thread.join() 不会导致线程终止,它会一直等到线程结束。结束其执行是线程的责任,例如定期检查某个条件(如标志)。

您已经有一个atomic 标志bReading,这似乎会导致线程退出。

        if (queueInput.empty()) {
            mtxQueueInput.unlock();
            if (bReading.load())
                continue;
            else
                break;  // thread will exit when queue is empty and bReading == false

所以你只需要在调用thread.join()之前在外线程中设置bReading = false

bReading = false;
reader.join();

请注意,您的线程中的bReading.store(false); 将无效。


注意:你不需要调用atomic.load()atomic.store(),你可以在你的代码中使用它们,这将隐式调用load()store()

【讨论】:

    【解决方案2】:

    我不知道停止thread 的内置可能性。由于您的线程中嵌入了endless-loop,因此它不会随时停止。

    std::thread::join 不会终止您的线程。当你需要它时,你必须实现一些东西来结束你的循环。

    • thread 必须退出时,您设置falsebool 变量。例如while(run) 或类似的东西;为简单起见,您还可以使用std::atomic&lt;bool&gt;
    • 您检查的信号变量。 std::condition_variable

    您现在所做的是,您在 main-thread 中等待您的 thread 终止。由于std::thread::join 不会终止您的thread,您的main-thread 将永远执行。

    注意:当您选择实施bool 解决方案时。你应该用mutex 或类似的东西来保护这个bool

    感谢您的评论。因为我不想让每个人都指向boost,但你提到了它。查找信息here

    【讨论】:

    • @MatthieuBrucher 谢谢,我在回答中链接了一个已回答的问题
    • Re,“我不知道有内置的可能性来停止线程。”这是有原因的:一个线程停止另一个线程没有安全的方法。不在任何语言中,不在任何系统上。这是因为线程的性质:它们对共享数据进行操作,并且永远无法知道其他线程是否已完成更新某些共享数据的一半,因此,如果您在那一刻强制它停止,它会离开数据处于损坏状态。线程之间必须始终合作。如果你想让线程 S 停止,那么你必须设计一种方式来要求它停止。
    【解决方案3】:

    问题不在于join,它(顺便说一句)不是用来停止或终止线程的。

    你的线程正在执行的函数包含一个永远不会终止的while(true),因为它只能休眠和解锁锁,没有别的。

    这意味着bReading.store 将永远不会被调用,因此在主线程循环中,您将始终通过 is 的这个分支

    if (bReading.load())
            continue;
    

    意味着main 也将永远执行。


    std::join 用于从一个线程等待另一个线程已完成其工作。当您从main 线程执行thread1.join() 时,会发生main等待,直到thread1 完成执行,然后再执行任何其他指令。

    【讨论】:

      猜你喜欢
      • 2016-06-30
      • 2019-12-29
      • 1970-01-01
      • 2010-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多