QThread cannot be stop after QCamera->start()
- 
hey guys. 
 6.9.3+vs2022.
 I wanna capture a usb cam video. it works find but the thread for capturing cannot be stop.
 when I exit the app, thread.wait() cannot return after runing run() function ,even i already run stop().
 If I donot do anything , wait() works fine and can return.
 why wait() cannot return?mainwindow.cpp, two button, one for start , another for stop: #include "mainwindow.h" #include "ui_mainwindow.h" #include <QCamera> #include <QDebug> #include <QCameraDevice> #include <QMediaDevices> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(this,&MainWindow::sigStart,&m_cam,&CamOperator::run); connect(this,&MainWindow::sigStop,&m_cam,&CamOperator::stop); // qDebug() <<"ui:"<<QThread::currentThread(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { emit sigStart(); } void MainWindow::on_pushButton_2_clicked() { emit sigStop(); }wrapper for qcamera: #include "camoperator.h" #include <QDebug> #include <QImage> #include <QDateTime> #include <QTimer> #define T_DBG qDebug() #define T_ERR qDebug() CamOperator::CamOperator(QObject *parent) : QObject{parent} { moveToThread(&m_bgThread); m_bgThread.start(); } CamOperator::~CamOperator() { stop(); if(m_bgThread.isRunning()){ T_DBG<<"stop cam..."; m_bgThread.requestInterruption(); m_bgThread.quit(); if(1){ T_DBG<<"wait thread end..."; // 3000 right here, after run(), it cannot return anymore. m_bgThread.wait(); } T_DBG<<"thred end"; } } void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera = new QCamera(cam); m_captureSession.setCamera(m_camera); m_imageCapture = new QImageCapture; m_captureSession.setImageCapture(m_imageCapture); connect(m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); }); connect(m_imageCapture,&QImageCapture::readyForCaptureChanged,this,[=](bool ready){ if(ready){ m_imageCapture->capture(); //qDebug()<<"ready"; } }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera->start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; } void CamOperator::stop() { if(m_camera){ m_camera->stop(); disconnect(m_imageCapture); delete m_imageCapture; delete m_camera; m_camera = nullptr; } emit sigErrorReport("camClosed"); T_DBG <<"stop end"; }#ifndef CAMOPERATOR_H #define CAMOPERATOR_H #include <QThread> #include <QCamera> #include <QImageCapture> #include <QCameraDevice> #include <QMediaDevices> #include <QMediaCaptureSession> class ICameraWrapper; class CamOperator : public QObject { Q_OBJECT public: explicit CamOperator(QObject *parent = nullptr); ~CamOperator(); signals: void sigErrorReport(const QString &); void sigImageReady(const QImage &); public slots: void run(); void stop(); private: QString m_camType; QCamera *m_camera{}; QImageCapture *m_imageCapture; QMediaCaptureSession m_captureSession; QThread m_bgThread; }; #endif // CAMOPERATOR_H
- 
hey guys. 
 6.9.3+vs2022.
 I wanna capture a usb cam video. it works find but the thread for capturing cannot be stop.
 when I exit the app, thread.wait() cannot return after runing run() function ,even i already run stop().
 If I donot do anything , wait() works fine and can return.
 why wait() cannot return?mainwindow.cpp, two button, one for start , another for stop: #include "mainwindow.h" #include "ui_mainwindow.h" #include <QCamera> #include <QDebug> #include <QCameraDevice> #include <QMediaDevices> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); connect(this,&MainWindow::sigStart,&m_cam,&CamOperator::run); connect(this,&MainWindow::sigStop,&m_cam,&CamOperator::stop); // qDebug() <<"ui:"<<QThread::currentThread(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { emit sigStart(); } void MainWindow::on_pushButton_2_clicked() { emit sigStop(); }wrapper for qcamera: #include "camoperator.h" #include <QDebug> #include <QImage> #include <QDateTime> #include <QTimer> #define T_DBG qDebug() #define T_ERR qDebug() CamOperator::CamOperator(QObject *parent) : QObject{parent} { moveToThread(&m_bgThread); m_bgThread.start(); } CamOperator::~CamOperator() { stop(); if(m_bgThread.isRunning()){ T_DBG<<"stop cam..."; m_bgThread.requestInterruption(); m_bgThread.quit(); if(1){ T_DBG<<"wait thread end..."; // 3000 right here, after run(), it cannot return anymore. m_bgThread.wait(); } T_DBG<<"thred end"; } } void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera = new QCamera(cam); m_captureSession.setCamera(m_camera); m_imageCapture = new QImageCapture; m_captureSession.setImageCapture(m_imageCapture); connect(m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); }); connect(m_imageCapture,&QImageCapture::readyForCaptureChanged,this,[=](bool ready){ if(ready){ m_imageCapture->capture(); //qDebug()<<"ready"; } }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera->start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; } void CamOperator::stop() { if(m_camera){ m_camera->stop(); disconnect(m_imageCapture); delete m_imageCapture; delete m_camera; m_camera = nullptr; } emit sigErrorReport("camClosed"); T_DBG <<"stop end"; }#ifndef CAMOPERATOR_H #define CAMOPERATOR_H #include <QThread> #include <QCamera> #include <QImageCapture> #include <QCameraDevice> #include <QMediaDevices> #include <QMediaCaptureSession> class ICameraWrapper; class CamOperator : public QObject { Q_OBJECT public: explicit CamOperator(QObject *parent = nullptr); ~CamOperator(); signals: void sigErrorReport(const QString &); void sigImageReady(const QImage &); public slots: void run(); void stop(); private: QString m_camType; QCamera *m_camera{}; QImageCapture *m_imageCapture; QMediaCaptureSession m_captureSession; QThread m_bgThread; }; #endif // CAMOPERATOR_H@QtTester said in QThread cannot be stop after QCamera->start(): m_captureSession This lives in the wrong thread since you don't pass a parent. 
 Why a thread at all? Please follow the official examples when you really want a thread here.
- 
@QtTester said in QThread cannot be stop after QCamera->start(): m_captureSession This lives in the wrong thread since you don't pass a parent. 
 Why a thread at all? Please follow the official examples when you really want a thread here.@Christian-Ehrlicher 
 thanks for replying.
 I have not found any thread programing for QCamera/QMediaCaptureSession,
 the example in Examples\Qt-6.9.3\multimedia\camera\ use UI thread ?
 can you suggest some web-link?
- 
@Christian-Ehrlicher 
 thanks for replying.
 I have not found any thread programing for QCamera/QMediaCaptureSession,
 the example in Examples\Qt-6.9.3\multimedia\camera\ use UI thread ?
 can you suggest some web-link?@QtTester said in QThread cannot be stop after QCamera->start(): I have not found any thread programing for QCamera/QMediaCaptureSession, It's not dedicated to QCameraonly. I think @Christian-Ehrlicher was referring to the general Qt Multithreading examples and documentation
- 
@Christian-Ehrlicher 
 thanks for replying.
 I have not found any thread programing for QCamera/QMediaCaptureSession,
 the example in Examples\Qt-6.9.3\multimedia\camera\ use UI thread ?
 can you suggest some web-link?
- 
@QtTester said in QThread cannot be stop after QCamera->start(): @jsulm for not stucking the UI? I donot know whether it is appropriate to use a thread. Please run and study the official Camera Example: https://doc.qt.io/qt-6/qtmultimedia-camera-example.html It shows that you don't need threads -- QCamera/QMediaCaptureSession does not block the UI. 
- 
@QtTester said in QThread cannot be stop after QCamera->start(): @jsulm for not stucking the UI? I donot know whether it is appropriate to use a thread. Please run and study the official Camera Example: https://doc.qt.io/qt-6/qtmultimedia-camera-example.html It shows that you don't need threads -- QCamera/QMediaCaptureSession does not block the UI. 
- 
@JKSH I read the code. 
 but what I am curious is : why qthread.wait() not return after qcamera.start() ?@QtTester said in QThread cannot be stop after QCamera->start(): why qthread.wait() not return after qcamera.start() I already told you what you might did wrong m_captureSessionThis lives in the wrong thread since you don't pass a parent. 
- 
@QtTester said in QThread cannot be stop after QCamera->start(): why qthread.wait() not return after qcamera.start() I already told you what you might did wrong m_captureSessionThis lives in the wrong thread since you don't pass a parent. @Christian-Ehrlicher 
 if i donot new the class, wait() works fine, event i call qcamera.start():void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera.setCameraDevice(cam); m_captureSession.setCamera(&m_camera); m_captureSession.setImageCapture(&m_imageCapture); m_captureSession.setVideoSink(&m_vs); connect(&m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); }); connect(&m_vs, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) { m_imageCapture.capture(); }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera.start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; }but if i new the class and pass parent,wait() won't return anymore, why the parent will stuck it?: void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera = new QCamera(cam,this); m_camera->setCameraDevice(cam); m_captureSession = new QMediaCaptureSession(this); m_captureSession->setCamera(m_camera); m_imageCapture = new QImageCapture(this); m_captureSession->setImageCapture(m_imageCapture); m_captureSession->setVideoSink(&m_vs); connect(m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); //qDebug()<<"cap:"<<QThread::currentThread(); }); connect(&m_vs, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) { m_imageCapture->capture(); }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera->start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; }
- 
@Christian-Ehrlicher 
 if i donot new the class, wait() works fine, event i call qcamera.start():void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera.setCameraDevice(cam); m_captureSession.setCamera(&m_camera); m_captureSession.setImageCapture(&m_imageCapture); m_captureSession.setVideoSink(&m_vs); connect(&m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); }); connect(&m_vs, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) { m_imageCapture.capture(); }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera.start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; }but if i new the class and pass parent,wait() won't return anymore, why the parent will stuck it?: void CamOperator::run() { auto cam = QMediaDevices::defaultVideoInput(); T_DBG <<QThread::currentThread(); if(cam.isNull()){ T_ERR <<"no usb cam"; goto fail; } m_camera = new QCamera(cam,this); m_camera->setCameraDevice(cam); m_captureSession = new QMediaCaptureSession(this); m_captureSession->setCamera(m_camera); m_imageCapture = new QImageCapture(this); m_captureSession->setImageCapture(m_imageCapture); m_captureSession->setVideoSink(&m_vs); connect(m_imageCapture,&QImageCapture::imageCaptured,this,[=](int id,const QImage &i){ emit sigImageReady(i); //qDebug()<<"cap:"<<QThread::currentThread(); }); connect(&m_vs, &QVideoSink::videoFrameChanged, [&]( const QVideoFrame &frame ) { m_imageCapture->capture(); }); emit sigErrorReport("openCamOk"); T_DBG <<"start capture"; m_camera->start(); goto end; fail: emit sigErrorReport("openCamFail"); end: T_DBG <<"start cap end"; }I also don't understand why you are using ugly GOTOstatements?!
 They are bad in 99.9% of all situations, especially in event driven programs. While there are some extremly niche use cases to use them at all, yours is not one of them.Just put the failcode where your jump instruction is... emit the signal andreturn.
 Then you also don't need to jump to someend.
 


