2011-10-23 94 views
0

我有兩個類 - 一個運行在主線程中,執行GUI操作,另一個執行一些計算併發出網絡請求。爲什麼不調用這個類的析構函數?

// A member of the class that runs in the main thread 
QThread thread; 

這裏是從類的初始化方法,該方法在主線程運行的片段:

// Create the class that runs in the other thread and move it there 
CServerThread * server = new CServerThread; 
server->moveToThread(&thread); 

// When the thread terminates, we want the object destroyed 
connect(&thread, SIGNAL(finished()), server, SLOT(deleteLater())); 
thread.start(); 

在析構函數,在主線程運行類:

if(thread.isRunning()) 
{ 
    thread.quit(); 
    thread.wait(); 
} 

我期望發生的是線程終止並銷燬CServerThread類的實例。但是,CServerThread類的析構函數未被調用。

回答

4

QThread::quit()停止該線程的事件循環。

通知返回代碼爲0(成功)的線程的事件循環退出。

QObject::deleteLater()需要事件循環的「擁有」線程被激活:

調度此對象爲刪除。
當控件返回到事件循環時,該對象將被刪除。

因此,您的對象的析構函數將不會運行,finished信號被解僱太遲。

考慮下面的人爲的例子:

#include <QThread> 
#include <iostream> 

class T: public QObject 
{ 
    Q_OBJECT 

    public: 
     QThread thr; 
     T() { 
      connect(&thr, SIGNAL(finished()), this, SLOT(finished())); 
     }; 
     void start() { 
      thr.start(); 
      std::cout << "Started" << std::endl; 
     } 
     void stop() { 
      thr.quit(); 
      std::cout << "Has quit" << std::endl; 
     } 
     void end() { 
      thr.wait(); 
      std::cout << "Done waiting" << std::endl; 
     } 
    public slots: 
     void finished() { 
      std::cout << "Finished" << std::endl; 
     } 
}; 

如果您撥打:

T t; 
t.start(); 
t.stop(); 
t.end(); 

輸出將是:

Started 
Has quit 
Done waiting 
Finished 

finishedwait完成之後被觸發。如果您的deleteLater連接有效,則該線程的事件循環已經死機。

+0

感謝您的解釋......但不是'deleteLater()'從主線程的上下文而不是我創建的'QThread'的調用? –

+0

'完成的'信號由您的線程發出。由於您的服務器也屬於該線程,因此處理將發生在線程中,而不是主線程中。 (見[這裏](http://doc.qt.nokia.com/4.7/threads-qobject.html)在最底部,'自動連接'描述) – Mat

+0

不會使用'Qt :: DirectConnection'導致插槽在主線程中運行?哪個線程正在發出'finished()'信號? –

相關問題