C ++ std :: поток завершается без активного исключения Прервано - PullRequest
0 голосов
/ 11 ноября 2019

У меня есть код, который захватывает видеопоток с камеры, выполняющей операцию захвата видео, в отдельном потоке. Код компилируется, но когда я пытаюсь его запустить, я получаю следующую ошибку:

Я провел некоторое исследование и обнаружил, что эта проблема связана с отсутствием th.join();, но я уже делаю это, когда пользовательпрерывает процесс нажатием клавиши q. До тех пор код должен продолжать работать в созданном потоке. Так что это говорит мне о том, что я должен присоединиться к потоку где-то еще.

Если я удалю поток, заменив thread th(&VideoCaptureAsync::update, this); на VideoCaptureAsync::update(); и удалив th.join();, ошибка исчезнет, ​​но это, очевидно, отрицательно скажется на целиэтот код.

Выход

Внутри функции инициализации

(процесс: 10748): GStreamer-CRITICAL **: gst_element_get_state: assertion 'GST_IS_ELEMENT (element) 'не удалось

Внутренняя функция запуска

Внутренняя функция обновления

завершить вызов без активного исключения

Внутренняя функция чтения

Прервано (ядро сброшено)

Код

/*
* 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();

}

1 Ответ

0 голосов
/ 11 ноября 2019

В вашем методе start ():

thread th(&VideoCaptureAsync::update, this);

Этот оператор создает новый локальный объект в методе start() с именем th, совершенно новый, только что с конвейера, std::thread объект и создает его таким образом, чтобы создать новый поток выполнения.

Сразу после этого возвращается start(). Это уничтожает этот локальный объект, вызывает его деструктор и приводит к вашему исключению.

Очевидно, что вы намерены использовать член класса th для создания нового потока выполнения вместо создания нового локального объектав методе start(). Но приведенный выше синтаксис C ++ является объявлением. Он объявляет новый объект, и когда используется в функции стороны, он создает новый локальный объект (в автоматической области видимости), который автоматически уничтожается в конце области действия. Вот как работает C ++.

Чтобы начать новый поток выполнения с существующего члена класса:

th=thread{&VideoCaptureAsync::update, this};

(с использованием современного синтаксиса инициализации C ++ современного C ++). Для получения дополнительной информации см. « Отложенный запуск потока в C ++ 11 ».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...