2012-03-15 56 views
2

正如this question中所建議的那樣,我現在正在嘗試合併多線程。關於在我的應用程序中實現QThread的問題?

根據the links given by karlphillip,我知道不應遵循有關繼承QThread的文檔,並按照說明使用moveToThread()。現在我看到QThread run()的默認實現只有一個exec(),然後必須在工作線程完成操作時調用quit()來結束。我有幾個問題,現在讓我更好地瞭解事情:

QApplication* ptrApp=new QApplication(argc,argv); 
QThread* th=new QThread; 
MyClass* obj=new MyClass; 
obj->moveToThread(th); 
QObject::connect(th,SIGNAL(started()),obj,SLOT(someFunct())); 
QObject::connect(obj,SIGNAL(over()),th,SLOT(quit())); 
th->start(); 
//some GUI code in main thread here 
return ptrApp->exec(); 
  1. ,如果我繼續使用someFunct()我發出over()即使從someFunct()內會發生什麼?它是未定義的行爲還是正常的?

  2. 哪個線程現在應與obj關聯(而發出over()後的其餘代碼仍在someFunct中執行)?我的理解是:它不能在th,當我有quit()那個線程... quit()將排隊,直到exec()在主線程執行它,這將導致exec()run()th退出(我希望我不是一個錯誤在這裏)。我假設線程不再存在。

  3. 一旦th插槽quit()執行,是安全的假設線程確實已經退出,還是應該我的thfinished()信號進一步連接到某些插槽是絕對肯定嗎?

回答

0

1.如果我繼續使用someFunct()我發出over()即使從someFunct()內會發生什麼?它是未定義的行爲還是正常的?

當你正在使用直接連接,發射over將直接調用該函數quit其停止事件循環,並從EXEC在線程的run方法返回。這意味着someFunct()將不會完成其執行並且其中的對象將丟失或處於部分修改狀態。

2.哪個線程會obj現在被關聯(而在發射over()之後的其餘代碼仍然在someFunct中執行)?

如前所述somefunct將不會完成其執行。但我相信任何與此線程相關的對象將保持原樣。我說我相信,因爲在任何地方都沒有堅實的斷言,但它最有意義。 As mentioned in the doc,對於這些對象發送或接收事件的線程必須重新啓動....

3.一旦執行插槽退出()執行,是否可以安全地假設線程確實退出或應該我進一步將完成的()信號連接到某個插槽以絕對確定?

quit()終止事件循環並返回exec()被調用。

請注意,對象Qthread不是線程。所以直到你輸入exec(),它是正在運行的主線程...以及它是在exec之後運行的主線程。

反正這些都是一些重大問題...

1
  1. 如果事件循環終止不要緊,somefunct()將繼續運行,直到它給控制權交還給現已滅絕循環。

  2. obj保持與線程關聯,因此如果發射連接到其中一個插槽的信號,該插槽將不會運行,但會在/重新啓動線程時排隊。
    如果QThread對象被刪除,obj->thread()返回0,所以我想這將是等效於調用obj->moveToThread(0)並根據文檔:

    如果targetThread爲零,所有針對這個對象的事件處理及其子站。

  3. quit()終止事件循環,則finished()信號從線發射,並且線程終止。
    因此,即使您收到finished()信號,您也不應該認爲線程已完成。在收到該信號後,您可以使用主線程中的QThread::wait來確保。
    如果線程處於完成狀態,QThread析構函數已經調用wait,因此您可以安全地刪除finished()信號後的線程(使用deleteLater()更安全)。

+0

感謝 1.亞這就是我被注意到的行爲......只是想確保它不是未定義/非法或東西 2.確定...請告訴我,如果我刪除會發生什麼QThread指針'th'(現在因爲我們不能重新啓動線程了,我想) 3. for'quit()'我明白,它將在隊列中執行直到'exec()'在主線程中執行它...但'finished()'是一個不需要任何事件循環的信號,它是終止線程所要做的最後一件事情,爲什麼需要另外指定'QThread :: wait()'使用'finished()'信號? – ustulation 2012-03-16 11:59:41

+0

對於2.您可以根據需要隨時停止並重新啓動線程。對於3.發射信號不需要事件循環。無論如何,連接它的插槽應該在另一個線程中運行事件循環(線程eventloop不能接收到它自己的finished()信號)。但在查看QThread的來源後,我認爲在大多數情況下,您可以等待完成的信號。 – alexisdm 2012-03-16 14:21:52

相關問題