2015-02-23 68 views
1

如果我有使用的QThread這樣的最標準代碼:Qt:如何清理QThread,而不是繼承它?

myClass* object = new myClass(); 
QThread* worker = new QThread(); 
object->moveToThread(worker); 
worker->start(); 

那麼什麼是刪除對象和退出工人線程的正確方法的正確方法?

如果我不刪除對象會出現內存泄漏。

如果我不退出工作人員,當我關閉應用程序時,會有警告說QThread在它仍在運行時被破壞。

+1

你知道[QtConcurrent ::運行(http://qt-project.org/doc/qt-4.8/qtconcurrentrun。 HTML)?它使用一個線程池,並且你只是給它一個函數來執行另一個線程。比使用QThread更容易。 – sashoalm 2015-02-23 10:05:29

+0

@sashoalm我知道我們可以繼承QThread並重寫run函數,它會由start()調用觸發,但不會深入。 – Nyaruko 2015-02-23 10:06:51

+0

我不確定你是否瞭解我告訴你的。 – sashoalm 2015-02-23 10:07:32

回答

3

要刪除您object對象,您可以將worker對象的QThread::finished信號連接到您的object對象的QObject::deleteLater插槽。

並且退出你的線程,你可以在你的類的析構函數中調用​​和QThread::wait(或者當你需要停止你的線程時)。

MyClass::~MyClass() 
{ 
    thread->quit(); 
    thread->wait(); 
    ... 
} 

要刪除您worker對象,你可以設置一個家長給它,或使其自動成員變量。你也可以使用智能指針。

順便說一句,你的命名約定是有點奇怪。您案例中的QThread對象不是工作者,它只是管理線程。 myClass對象將是您的案例中的工作者。

+0

在這種情況下,quit()和terminate()之間有什麼區別? – Nyaruko 2015-02-23 08:57:11

+1

@saZ你想在線程中等待嗎? 'thread()'返回對象的當前線程。你會在那裏等待,因爲你在那裏阻塞線程。您應該等待使用'myClass'的類的析構函數。 – Nejat 2015-02-23 09:00:05

+0

@Nejat我失敗了,你就在那裏 – 2015-02-23 09:10:00

0

這是一個基本用法:

定義工人階級:

class MyWorkerClass { 
    signals: 
    void Finished(); 

    public slots: 
    void RunCode(){ 
     //... 
     // add your code here 
     //... 
     emit Finished(); 
    } 
} 

如何使用您的工人階級:

MyWorkerClass * workerObject = new MyWorkerClass(); 
QThread * workerThread = new QThread(); 

workerObject->moveToThread(workerThread); 

connect(workerThread, &QThread::started, workerObject, &MyWorkerClass::RunCode); 
connect(workerObject, &MyWorkerClass::Finished, workerThread, &QThread::quit); 

workerThread->start(); 
workerObject->deleteLater(); 
0

連接QThread::finishedQObject::deleteLater是錯誤的。如果發出信號QThread::finished,這意味着線程事件循環將不會再次運行,因此不會調用slot QObject::deleteLater。所以接受的答案是錯誤的。

這是更好地做這樣的:

myClass* object = new myClass(); 
QThread* worker = new QThread(parent); 
object->moveToThread(worker); 

connect(object, &QObject::destroyed, worker, &QThread::quit, Qt::DirectConnection); 
connect(someObject, SIGNAL(stoItSignal()), object, &QObject::deleteLater); 
worker->start(); 

在某個時候可能需要等待胎面,(例如,當主窗口被銷燬),收拾東西,所以這個說法可能是有用的(在這種情況下Qt::DirectConnection在上面的代碼是強制性的):

object->deleteLater(); 
worker->wait(3000); 
+0

文檔說:[*從Qt 4.8開始,可以通過連接finished()信號到QObject來釋放剛剛結束的線程中的對象: deleteLater()*](http://doc.qt.io/qt-5/qthread.html#managing_thread)。所以這沒有錯。該文檔還說明了'QThread :: finished':[*當這個信號發出時,事件循環已經停止運行。除了延遲刪除事件外,線程中不會再處理任何事件。該信號可以連接到QObject :: deleteLater(),以釋放該線程中的對象。*](http://doc.qt.io/qt-5/qthread.html#finished) – thuga 2015-02-23 09:36:49