How to stop the thread execution in C++

那年仲夏 提交于 2020-07-28 04:43:45

问题


I created one thread in my main program, thread execution has to stop once the main program will terminate. I am using reader.join(); to terminate the thread execution. But it is not stopping the execution.

I tried with below-mentioned code, I am using thread.join(); function, but it is failed to terminate a thread. And after the main program also my thread is kept executing.

#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;
}

回答1:


thread.join() does not cause the thread to terminate, it waits until the thread ends. It's the responsibility of the thread to end its execution, for example by periodically checking for a certain condition, like a flag.

You already have an atomic flag bReading, which appears to cause the thread to exit.

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

So all you need is to set bReading = false in the outer thread before calling thread.join().

bReading = false;
reader.join();

Note that bReading.store(false); inside your thread will have no effect.


Note: you don't need to call atomic.load() and atomic.store(), you can just use them in your code, which will call load() and store() implicitly.




回答2:


I'm not aware of an built in possibility to stop a thread. Since you have a endless-loop embedded in your thread, it won't stop at any time.

std::thread::join does not terminate your thread. You have to implement something to end your loop, when you demand it.

  • A bool variable you set false when the thread has to exit. e.g. while(run) or something like that; for simplicity you could also use a std::atomic<bool>
  • A signaling variable you check. std::condition_variable

What you do at the moment is, you wait in your main-thread that your thread terminates. Since std::thread::join does't terminate your thread, your main-thread will execute forever.

NOTE: When you choose to implement the bool solution. You should protect this bool with an mutex or something alike.

Thanks for the comment. As I don't want to point everyone to boost, but you mentioned it. Find information here.




回答3:


The problem is not with join which (btw) is not meant to be used to stop or terminate a thread.

The function that your thread is executing contains a while(true) which will never terminate, because it can only sleep and unlock the lock, nothing else.

This means that bReading.store will never be called and as a consequence in the main thread loop you will always go though this branch of the is

if (bReading.load())
        continue;

meaning that also the main will execute forever.


std::join is used to wait from a thread that another thread has completed its work. when you do thread1.join() from the main thread what happens is that main will wait until thread1 has completed its execution before executing any other instruction.



来源:https://stackoverflow.com/questions/55824719/how-to-stop-the-thread-execution-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!