[英]C++ std::thread terminate called without an active exception Aborted
我这里有一个代码,它从在单独线程中运行视频捕获操作的相机捕获视频 stream。 代码可以编译,但是当我尝试运行它时,我收到以下错误。
我做了一些研究,发现这个问题与缺少th.join();
相关。 但是当用户通过按q
键中断该过程时,我已经这样做了。 在那之前,代码应该继续在创建的线程中运行。 所以这告诉我应该在其他地方加入线程。
如果我通过替换thread th(&VideoCaptureAsync::update, this);
使用VideoCaptureAsync::update();
并删除th.join();
,错误消失了,但这显然违背了这段代码的目的。
Output
内部启动 function
(进程:10748):GStreamer-CRITICAL **:gst_element_get_state:断言“GST_IS_ELEMENT(元素)”失败
内部启动 function
内部更新 function
在没有活动异常的情况下调用终止
内读 function
中止(核心转储)
代码
/*
* Asynchronous_video_capture.cpp
*
* Copyright (C) 2019 C. S. G.
*
* MIT License
*/
#include <iostream> // for standard I/O
#include <string> // for strings
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp> // Video write
#include <opencv2/opencv.hpp>
#include <opencv2/core/utility.hpp>
#include <thread>
#include <tuple>
using namespace cv;
using namespace std;
void foo(bool &keep_run){
cout << "Inside the thread: Interrupt flag = " << keep_run << endl;
if (std::cin.get() == 'q') {
keep_run = false;
cout << "User Interrupted the process. Interrupt flag = " << keep_run << endl;
}
}
class VideoCaptureAsync
{
private:
VideoCapture cam;
thread th;
bool read_lock;
Mat frame;
Mat grabbed;
bool isStarted;
public:
void initiate(unsigned int camId, unsigned int width, unsigned int height, double fps);
void start(); // a start function to create and start the thread
void update(); // an update function that will be called asynchronously
tuple<Mat, Mat> read(); // a read function that we will call from our code to retrieve a new frame.
void stop(); // a stop function to stop (join) the thread
void exit(); // an __exit__ function to clean up some resources.
};
void VideoCaptureAsync::initiate(unsigned int camId, unsigned int width, unsigned int height, double fps){
cout << "Inside initiate function" << endl;
cam.open(camId);
if (!cam.isOpened())
{
cerr << "Could not open the VideoCapture camera: " << camId << endl;
}
cam.set(CV_CAP_PROP_FRAME_WIDTH, width);
cam.set(CV_CAP_PROP_FRAME_HEIGHT, height);
cam.set(CAP_PROP_FPS, fps);
isStarted = false;
read_lock = false;
VideoCaptureAsync::start();
}
void VideoCaptureAsync::start(){
cout << "Inside start function" << endl;
if (isStarted) {
cout << "Asynchroneous video capturing has already been started" << endl;
}
isStarted = true;
thread th(&VideoCaptureAsync::update, this);
//VideoCaptureAsync::update();
}
void VideoCaptureAsync::update(){
cout << "Inside update function" << endl;
while(isStarted){
Mat frame_update;
Mat grabbed_update;
tie(frame_update, grabbed_update) = VideoCaptureAsync::read();
if(!read_lock){
frame_update.copyTo(frame);
grabbed_update.copyTo(grabbed);
}
}
}
tuple<Mat, Mat> VideoCaptureAsync::read(){
cout << "Inside read function" << endl;
if (!read_lock){
read_lock = true;
Mat frame_read;
cam.read(frame_read);
Mat grabbed_read;
read_lock = false;
return make_tuple(frame_read, grabbed_read);
}
}
void VideoCaptureAsync::stop(){
cout << "Inside stop function" << endl;
th.join();
isStarted = false;
read_lock = true;
}
void VideoCaptureAsync::exit(){
cout << "Finished writing ..." << endl;
cam.release();
}
int main(int argc, char *argv[]){
const unsigned int camId = 1;
const bool enableOutput = true;
const unsigned int w = 1280;
const unsigned int h = 720;
double fps = 30.0;
VideoCaptureAsync obj;
obj.initiate(camId,w,h,fps);
bool keep_running = true;
thread th1(foo, std::ref(keep_running));
Mat original_frame;
while (keep_running) {
std::tie(std::ignore, original_frame) = obj.read();
if (enableOutput) {
imshow("Retrieved Image", original_frame);
waitKey(1000/fps);
}
}
obj.stop();
obj.exit();
}
在您的start
() 方法中:
thread th(&VideoCaptureAsync::update, this);
该语句在名为th
的start()
方法中创建了一个新的本地 object,一个全新的、刚下线的std::thread
object,并以创建新执行线程的方式构造它。
紧接着, start()
返回。 这会破坏这个本地 object,调用它的析构函数,并导致您的异常。
您的明显意图是使用th
成员来创建新的执行线程,而不是在start()
方法中创建新的本地 object 。 但是上面的 C++ 语法是一个声明。 It declares a new object, and when used in side a function it creates a new local object (in automatic scope), that gets automatically destroyed at the end of the scope. 这就是 C++ 的工作原理。
为了让新的执行线程从您现有的 class 成员开始:
th=thread{&VideoCaptureAsync::update, this};
(使用现代 C++ 的统一初始化语法)。 有关详细信息,请参阅“ C++11 中的线程延迟启动”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.