2015-02-01 2 views
5

OpenCV를 사용하여 카메라에서 비디오 피드를 캡처하는 간단한 Qt 프로그램을 작성하고 있습니다. 루프를 사용하여 이미지를 캡처하여 MainWindow 개체에 공급하는 QThread 개체를 사용하고 있습니다. 이것은 정상적으로 작동합니다.종료시 멀티 스레드 Qt 애플리케이션이 중지되지 않습니다.

문제는 내가 닫을 때 (즉, "X"를 누르면) 카메라 캡처 스레드가 멈추고 GUI가 사라진다는 것입니다. 그러나 프로그램은 여전히 ​​백그라운드에서 실행 중입니다. 또한 응용 프로그램 출력에 다음과 같은 경고 메시지가 표시됩니다.

QThread : 스레드가 실행 중일 때 삭제됩니다.

언제 응용 프로그램을 완전히 종료 할 수 있습니까?

MAIN.CPP

#include <QApplication> 
#include "application.h" 

using namespace cv; 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 

    Application app; 
    app.init(); 

    return a.exec(); 
} 

application.h

#include "mainwindow.h" 
#include "camerathread.h" 
#include "mathandler.h" 
#include "tools.h" 
#include "opencv2/core/core.hpp" 

#ifndef APPLICATION 
#define APPLICATION 

class Application : public MatHandler{ 
    MainWindow w; 
    CameraThread ct; 
public: 
    Application() { 
     w.setFixedSize(800,600); 
    } 

    void init() { 
     ct.setMatHandler(this); 
     ct.start(); 
     w.show(); 
    } 

    void handleMat(cv::Mat mat) { 
     QImage qImage = toQImage(mat); 
     w.setImage(qImage); 
    } 
}; 

#endif // APPLICATION 

camerathread

#include <QThread> 
#include "mathandler.h" 
#include "opencv2/highgui/highgui.hpp" 

#ifndef CAMERATHREAD 
#define CAMERATHREAD 

class CameraThread : public QThread { 
    MatHandler *matHandler; 
public: 
    ~CameraThread() { 
    } 

    void setMatHandler(MatHandler *h) { 
     matHandler = h; 
    } 

private: void run() { 
     cv::VideoCapture vc(0); 

     if (vc.isOpened()) { 
      for(;;) { 
       cv::Mat img; 
       vc >> img; 
       matHandler->handleMat(img); 
      } 
     } 
    } 
}; 

#endif // CAMERATHREAD 

프로그램 C 이보다 더 많은 코드를 제공하지만, 나는 그 질문과 관련이 있다고 생각하는 코드만을 포함하고있다. 필요한 경우 나머지를 게시합니다.

+0

UI 및 카메라 스레드 외에 다른 스레드가 실행되고 있는지 확인하십시오. 사용중인 API가 다른 스레드를 생성 할 수 있습니다. –

+0

나는 이것을 확인하는 방법을 모르겠다 ... 설명해 주시겠습니까? – gromit190

+0

실행중인 스레드를 확인하는 것은 사용중인 IDE에 따라 다릅니다 (소금이면 충분합니다). 예를 들어, 다음 검색 : https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=how%20to%20see%20running%20threads%20in%20eclipse이 결과를 산출했습니다. : http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.mat.ui.help%2Ftasks%2Fanalyzingthreads.html 그러나 다시 말하지만, 귀하의 IDE에 따라 다릅니다. 방금 샘플보기/w Eclipse를 시연했습니다. –

답변

3

코드에 중대한 문제가 있습니다. 응용 프로그램을 닫으려고 할 때 truefinishThread를 설정해야합니다

while(!finishThread) 
{ 
    cv::Mat img; 
    vc >> img; 
    matHandler->handleMat(img); 
} 

: 먼저 실행 기능의 모든 루프에 대한 끝없는 당신처럼 자기가 스레드 종료를 관리하지 않는 한 절대 멈추지하는 스레드의 원인이됩니다. finishThread의 값을 설정하는 슬롯을 제공하기 만하면됩니다. 스레드를 종료하려면 true 값을 사용하여 해당 슬롯에 연결된 신호를 내 보냅니다. 그 후 스레드가 몇 초 동안 제대로 끝날 때까지 기다려가 완료되지 않은 경우에 종료 강제 :

emit setThreadFinished(true); //Tell the thread to finish 
if(!ct->wait(3000)) //Wait until it actually has terminated (max. 3 sec) 
{ 
    ct->terminate(); //Thread didn't exit in time, probably deadlocked, terminate it! 
    ct->wait(); //We have to wait again here! 
} 

또한 당신이 직접 다른 스레드에서 handleMat 함수를 호출하지 않아야합니다. 응용 프로그램이 중단되거나 정의되지 않은 동작으로 이어질 수 있습니다. 이를 위해 신호/슬롯 메커니즘을 사용하십시오. 스레드의 신호를 해당 슬롯에 연결하고 호출 할 때마다 인수와 함께 신호를 내 보냅니다.

다른 점은 QObject에서 수업을 유도하고 moveToThread을 사용하는 것이 더 바람직하다는 것입니다. 당신은 당신의 클래스의 생성자에서이 작업을 수행 할 수 있습니다 :

th = new QThread(); 

this->setParent(0); 
this->moveToThread(th); 

QObject::connect(th,SIGNAL(started()),this,SLOT(OnStarted())); 
QObject::connect(th,SIGNAL(finished()),this,SLOT(OnFinished())); 

th->start(); 

귀하의 초기화 및 종료 작업은 각각 OnStarted()OnFinished() 슬롯에서이 작업을 수행해야합니다. 반복적 인 작업을 수행하는 작업자 기능을 가질 수 있습니다.

또한 소위 말하는 Application 클래스의 소멸자에서 말한 것과 같은 방법으로 스레드를 종료하십시오.

+0

피드백을 보내 주셔서 감사합니다. C++ 및 Qt 프로그래밍의 초보자로서 (이미 이미 깨달았 듯이) 정말 필요합니다. 하지만 한 가지는 분명하지 않습니다. 응용 프로그램을 중지하는 데 public void 메서드를 사용할 수있는 경우 CameraThread의 공용 슬롯을 사용해야하는 이유는 무엇입니까? 찬성/반대 의견은 무엇입니까? – gromit190

+1

메소드를 사용하여 응용 프로그램을 중지하면 실제로 위험한'Application'의'ct-> setFinished (true);'와 같이 직접 호출해야합니다. 그것은 두 개의 다른 스레드에 있고 두 개의 스레드에서 변수에 동시에 액세스하면 정의되지 않은 동작이 발생하기 때문입니다. 시그널/슬롯 메카니즘을 사용하여 쓰레드를 멈추게 할 때, 하나의 쓰래드에서만 변수가 액세스되는지 확인하십시오 (여기서는'CameraThread'). 다른 스레드에있는 객체의 함수를 절대 직접 호출하지 마십시오. – Nejat

+0

주목, 고마워. 주요 문제; 나는 당신이 제안한 것처럼 응용 프로그램 deconstructor에 ct-> stop 코드를 추가했습니다. 또한 Thread의 deconstructor에 QThread :: exit()가 추가되었습니다. 메인 윈도우를 닫은 후에도 응용 프로그램이 계속 실행 중입니다 ... – gromit190

관련 문제