2011-04-26 4 views
2

스레드가 실행을 완료하면 개체에 알리고 싶습니다. 그러나 스레드를 올바르게 종료 할 수 없습니다. ThreadWorker.cppQThread - 슬롯을 사용하여 종료 스레드를 종료하려면

void ThreadWorker::doSetup(QThread *thread, const string &path) 
{ 
    _strPath = path; 
    connect(thread, SIGNAL(started()), this, SLOT(run())); 
    connect(this, SIGNAL(finished()), thread, SLOT(quit())); //tried terminate() also 
} 


void ThreadWorker::run() 
{ 
    DirectorySearch dicSearch; 
    vector<string> vecFileList = dicSearch.getFileList(_strPath); 
    emit updateStatus("Directory Fetched"); 
    emit finished(); 
} 

(가) 종료

thread = new QThread; 
tw = new ThreadWorker; 
connect(tw, SIGNAL(updateStatus(QString)), this, SLOT(statusUpdate(QString))); 
tw->doSetup(thread, strDic); 
tw->moveToThread(thread); 
thread->start(); 

while(thread->isRunning()) 
{ 
} 

qDebug() << "Thread Finished"; 

은() 슬롯이 스레드를 중지하지 않는 것 (QThread :: isFinished는 결코 진정한 반환

Processor.cpp : 나는 다음과 같은 코드가 있습니다). 누군가 올바른 방향으로 나를 안내 할 수 있습니까?

(참고 : ThreadWorker는 QThread에서 상속하지 않습니다) ...

+2

테스트를 위해 ... while 루프에서 QCoreApplication :: instance() -> processEvents()를 추가하십시오. 이것은 제안 일 뿐이므로 답변으로 게시하지 않습니다. 이것은 QThread 자체가 주 스레드에 있기 때문에 작동 할 수 있습니다. 따라서 QThread에서 실행해야하는 ThreadWorker 슬롯 대신 OWN 슬롯이 기본 이벤트 루프에서 호출 될 수 있습니다. – Raiv

+0

@Raiv : spot-on, 나는 정상적인 작동에서'terminate()'를 사용하도록 권유받은 –

답변

4

메인 스레드에서 Processor.cpp이 실행된다고 가정하면 while(thread->isRunning()) 루프에 메인 스레드가 완전히 연결되어 있습니다. 즉, 응용 프로그램의 이벤트 루프가 처리를 수행 할 수 없으므로 예를 들어 updateStatus() 신호가 처리되지 않습니다. 덧글에서 언급했듯이 QThread 개체는 주 스레드에 의해 만들어지기 때문에 주 이벤트 루프가 그 일을 수행해야하기 때문에 신호가 작동하지 않습니다. 게다가, 작업 스레드가 뭔가를하기 위해 메인 스레드에서 기다리고 있다면 왜 작업자 스레드를 사용합니까? :)

이 슬롯 workDone()를 추가, while 루프를 제거하십시오 (또는 그것을 부르기 위하여 당신이 원한다 무엇 이건) Processor.cpp로하고 Threadworkerfinished() 신호에 그 연결합니다.

-1

대신하여 'doSetup'기능을하고 당신 moveToThread 전에, TW에서 TW의 부모에 SINGALS 슬롯 사이의 설정 연결.

4 개의 연결을 사용합니다. 첫 번째는 ThreadWorker의 run 메소드입니다. 그게 간단하고 자기 충분히 explainatory.

두 번째 신호는 완료 신호에서 세 번째 신호 연결까지입니다. 스레드를 종료시키는 신호

스레드의 terminate() 슬롯을 호출해야하는 신호에 세 번째. 이렇게하면 run 메서드에 연결할 때 이벤트 루프 설정을 효과적으로 닫습니다 (exec()는 start()를 호출 할 때 자동 호출 됨). run 메서드가 어떤 종류의 루프가 아니기 때문에 문제없이 스레드를 닫습니다.

Forth는 스레드의 terminated() SIGNAL에서 tw의 부모 슬롯에 있습니다. 이 시점에서 무언가를하고 싶다면 쓰레드가 죽었을 때 표시됩니다.

위의 연결을 수행합니다 (문자열을 전달해야하는 경우 run 메소드 및 해당 SIGNAL 연결에 변수를 추가하면 데이터가 있음). 스레드로 이동하고 스레드 시작으로 이동 한 다음 SIGNAL run 메소드에 첨부됩니다. 그 일을 시키십시오. 완료되면 스레드 종료 된 슬롯에 연결된 다른 신호에 연결되는 완료 신호를 처리합니다. 이렇게하면 이벤트 루프가 종료되고 스레드가 종료되어 종료 된 신호가 푸시되므로 무언가를 할 수 있습니다.

+0

-1이라고 생각한다. –

+0

내가 말한 이유는 그것이 실행 루프의 끝에서 결국 방출되는 신호를 통해 호출되기 때문입니다. 나는 실제로 위의 대답에서 언급. 일반적으로 당신은 그만두고 싶습니다 ... 그러나이 상황에는 아무런 차이가 없습니다. – g19fanatic

+0

잘못되었습니다. 슬롯의 원래의 문제는 실제로는 옆으로 부르지 않는다 :'quit()','ThreadWorker :: run()'은 자체적으로 정리할 수있다. 경주'terminate()'는'ThreadWorked :: run()'으로 제어가 되돌아 가기 전에 스레드를 죽일 수 있습니다. 로컬 객체의 소멸자는 호출되지 않습니다. –

3

나는 동일한 문제가있어서 대답을 찾았습니다.당신이해야 할 것은, 당신의 while 루프에서> processEvents() 대신 호출 -, 당신은 QCoreApplication :() 인스턴스를 실행할 필요가 없습니다 What is the use of QThread.wait() function?

이 문제를 해결하기 : 여기 내 질문입니다 생성하는 스레드의 이벤트 루프 (while 루프에 의해 차단됨)에 신호를 보내려고하는 quit()는 직접 호출해야합니다.

connect(this, SIGNAL(finished()), thread, SLOT(quit())); //tried terminate() also 

그리고 대신 :

그래서 당신의 코드 라인을 드롭

emit finished(); 

사용 :

this->thread()->quit(); 

타다 ... 문제가 해결. 교훈 : 신호가 예상되는 위치 (작업자 스레드의 이벤트 루프)에 도달하지 못하기 때문에 qt 신호 슬롯 메커니즘을 통해 작업자 스레드를 종료하려고하지 마십시오. 스레드 대신. 그 스레드가 무엇을하는지 결코 알지 못하며, 이벤트 루프가 실행 중이고 그렇지 않다면, 어쨌든 작업 스레드에 대해 비즈니스가되어서는 안됩니다 ... 대신, 직접 종료를 호출하십시오.

connect(this, SIGNAL(finished()), thread, SLOT(quit()), Qt::DirectConnection); 

이 스레드를 중지 :

1

당신은 Qt는 :: DirectConnection를 사용할 수 있습니다.

관련 문제