나는 정상적으로 그만 두라고 말하려고한다. 이를 위해 스레드는 모든 반복에서 전역 부울 플래그를 검사합니다.이 플래그는 스레드가 계속되거나 종료되어야하는지 여부를 나타냅니다. 내가 어떤 함수에서 true로 플래그를 설정하여 스레드를 중지하려고하면, 지금왜 내 스레드가 정상적으로 종료되지 않습니까?
ImageFusionQt::ImageFusionQt(QWidget* parent)
: QMainWindow(parent)
{
captureThread = new QThread();
captureWorker = new CaptureWorker();
// Connects the threads started() signal to the process() slot in the worker, causing it to start.
connect(captureThread, SIGNAL(started()), captureWorker, SLOT(process()));
// Connect worker finished signal to trigger thread quit, then delete.
connect(captureWorker, SIGNAL(finished()), captureThread, SLOT(quit()));
connect(captureWorker, SIGNAL(finished()), captureWorker, SLOT(deleteLater()));
// Make sure the thread object is deleted after execution has finished.
connect(captureThread, SIGNAL(finished()), captureThread, SLOT(deleteLater()));
// Give QThread ownership of Worker Object
captureWorker->moveToThread(captureThread);
captureThread->start();
}
CaptureWorker.cpp
void CaptureWorker::process()
{
while(true)
{
g_exit_lock->lockForRead();
if(g_exit)
{
g_exit_lock->unlock();
break;
}
g_exit_lock->unlock();
}
qDebug() << "CaptureWorker: Exiting.";
emit finished();
}
: 스레드는 다음과 같이 설정 (코드 http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/에서이다)이다 process() 메서드는 반환하지만 스레드가 완료되지 않고 wait()에 대한 호출이 영원히 차단됩니다. 내 스레드가 종료되지 않는 이유는 무엇입니까?
g_exit_lock->lockForWrite();
g_exit = true;
g_exit_lock->unlock();
QThread::sleep(15);
qDebug() << "ct finished? " << captureThread->isFinished();
captureThread->wait();
qDebug() << "All threads stopped.";
로그 파일 출력 :
2013.03.26 09:29:22[D] CaptureWorker: Exiting.
2013.03.26 09:29:37[D] ct finished? false
UPDATE
좀 디버깅을했고, 일부 intersting 물건을 발견 : 그 이벤트 루프에서
- 스레드 블록 (QEventLoop를 :: exec). 그것은 분명히받지 못하는 quit() 신호를 기다립니다.
- process()가 반환 된 후 스레드의 이벤트 루프가 생성됩니다. 입니다. 내가했던 것처럼 신호를 연결하면 스레드가 이미 작업을 마친 후에 (예 : process()가 반환 된 경우) 스레드의 run() 메서드가 호출됩니다.
- 이벤트 루프는 실제 루프를 수행하기 전에 게시 된 모든 종료 이벤트를 지 웁니다.
내 결론
- 내가 이벤트 루프가 종료() 멤버를 호출
- 을 확정되는 시점에 이벤트가 삭제됩니다) (때문에 일을 그만 두지 않는 한 것처럼 종료() 슬롯에 연결 함수를 스레드 객체에 직접 적용하면 정상적으로 종료됩니다. 이것은 QThread :: currentThread() -> quit();을 사용하여 외부 또는 내부에서 수행 할 수 있습니다.
열기 질문
- 이벤트 루프가 설립 된 후 과정() 메서드를 호출 할 수있는 방법이 있나요?
- 작업이 모두 완료되면 이벤트 루프가 생성되는 것은 잘못되었습니다. 그러나 내가 QThread를 사용하는 방식은 다음과 같습니다. docs
아마도 디버그 스트림을 플러시해야합니까? – Nick
finished()의 내용은 무엇입니까? –
로깅은 프로그램을 디버깅하는 데 매우 비생산적인 방법입니다. 대신 디버거를 사용하는 방법에 대해 알아보십시오. 디버거를 연결하고, 프로그램을 중단하고, 컨텍스트를 작업자 스레드로 전환하고 스택 추적에서 수행중인 작업을 찾으십시오. 높은 확률로 이제는 루프를 실행하지 않고 어떤 종류의 OS 호출에 묻혀서 캡처가 완료 될 때까지 기다릴 것입니다. 따라서 g_exit을 테스트하지 않으므로 종료하지 않습니다. –