如何停止C ++中的线程执行

时间:2019-04-24 07:39:22

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

我在主程序中创建了一个线程,一旦主程序终止,线程执行必须停止。我正在使用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;
}

3 个答案:

答案 0 :(得分:4)

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

因此,您所需要做的就是在调用bReading = false之前在外部线程中设置thread.join()

bReading = false;
reader.join();

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


注意:您不需要调用atomic.load()atomic.store(),只需在代码中使用它们即可,它们将隐式调用load()store()。 / p>

答案 1 :(得分:1)

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

std::thread::join不会终止您的线程。您必须在需要时实施一些措施来结束循环。

  • bool必须退出时,您设置了false的{​​{1}}变量。例如thread或类似的东西;为简单起见,您还可以使用while(run)
  • 您检查的信号变量。 std::atomic<bool>

此刻,您正在std::condition_variable中等待main-thread终止。由于thread不会终止您的std::thread::join,因此您的thread将永远执行。

注意:当您选择实施main-thread解决方案时。您应该使用bool或类似的东西来保护此bool

感谢您的评论。因为我不想将所有人都指向mutex,但是您提到了它。查找信息here

答案 2 :(得分:0)

问题不是join引起的,while(true)并不是用来停止或终止线程的。

您的线程正在执行的函数包含一个bReading.store,它将永远不会终止,因为它只能休眠并解锁该锁,而没有其他任何作用。

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

main

意味着std::join也将永远执行。


thread1.join()用于从一个线程等待另一个线程完成其工作。当您从main线程执行main时,会发生thread1等待,直到@Path("/api") public class Service1 { final Logger logger = Logger.getLogger(Service1.class); @POST @Path("/testtransfer") @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML) public String testtransfer(String name) throws SQLException { logger.info("Service is:" + "InternalAccountTransfer"); PreparedStatement pstmt = null; Connection conn = null; FDIdGenerator f = new FDIdGenerator(); String Id = f.generate(); try { conn = DBUtil.getDataSource().getConnection(); } catch(Exception e) { e.printStackTrace(); } try{ pstmt = conn.prepareStatement( "insert into EXTB_XML_REQ_RES(ID,SERVICE,OBX_REQ)values(?,?,?)"); pstmt.setString(1,Id); pstmt.setString(2,"InternalAccountTransfer"); pstmt.setString(3,name); System.out.println(pstmt + "......pstmt....."); pstmt.executeUpdate(); conn.commit(); logger.info("REQ is:" + "Inserted"); } catch(Exception e) { e.printStackTrace(); } finally {if(conn != null) { conn.close(); } } String START = ""; String END = ""; String Content = ""; String xml = ""; String response = ""; /* HashMap<String, String> response = new HashMap<String, String>(); */ InputStream in = this.getClass().getClassLoader() .getResourceAsStream("config.properties"); Properties prop = null; prop = new Properties(); try { prop.load(in); } catch (IOException e1) { e1.printStackTrace(); } String SOAPAction = prop.getProperty("SOAPACTION"); START = "<CREATETRANSACTION_FSFS_REQ xmlns=\"http://fcubs.ofss.com/service/FCUBSRTService\">\r\n"; BufferedReader br = null; String sCurrentLine = ""; Content = name.substring(name.indexOf("<FCUBS_HEADER>"), name.indexOf("</FCUBS_BODY>") + 13); END = "</CREATETRANSACTION_FSFS_REQ>\r\n"; /* xml = XML.toString(json); */ xml = START + Content + END; System.out.println(xml + "............xml..................."); xml = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:fcub=\"" + SOAPAction + "FCUBSRTService\">\r\n" + " <soapenv:Header/>\r\n" + "<soapenv:Body>" + xml + " </soapenv:Body>\r\n" + "</soapenv:Envelope>"; System.out.println(xml + "...........xml........"); WebServiceCall wsc = new WebServiceCall(); logger.info("Before Calling The Webservice XML is :" + xml); response = wsc.WebserviceInternalAccountTransfer(xml,Id); return response.toString(); } 完成执行之前再执行任何其他指令。