我想知道如何正確地停止QThread。我havea無限循環中的一個線索,我想阻止它,當我做了具體的行動:如何在QT中停止qThread
我曾嘗試:
if (thread->isRunning()){
worker->stop();
thread->terminate();
}
的stop()方法設置一個值,以假出去我的無限循環。此外,我並不真正瞭解quit(),terminate()或wait()之間的區別。有人能解釋我嗎?
謝謝。
我想知道如何正確地停止QThread。我havea無限循環中的一個線索,我想阻止它,當我做了具體的行動:如何在QT中停止qThread
我曾嘗試:
if (thread->isRunning()){
worker->stop();
thread->terminate();
}
的stop()方法設置一個值,以假出去我的無限循環。此外,我並不真正瞭解quit(),terminate()或wait()之間的區別。有人能解釋我嗎?
謝謝。
一個正確的答案取決於你如何實際使用QThread以及你如何實現stop()。
的Qt中打算用例假定以下模型:
現在你需要了解一些內部的實際內容。在Qt中有幾個「模型」的信號,在某些情況下,當您「發送信號」時,您只需調用一個「插槽」功能。這是一個「直接」插槽連接,在這種情況下,slot()將在調用者線程中執行,其中一個提示信號。所以爲了與另一個線程通信,Qt允許使用另一種信號,即「排隊連接」。呼叫者不會調用槽(),而是將消息留給擁有該槽的對象。與此對象關聯的線程將讀取此消息(稍後的一段時間)&執行slot()本身的執行。
現在您可以瞭解創建和執行QThread時發生了什麼。一個新創建的線程將執行QThread :: run(),默認情況下,它將執行Qthread :: exec(),它不是任何內容,而是一個無限循環,用於查找與線程關聯的對象的消息並將它們傳輸到這些對象的槽。調用QThread :: quit()將結束消息發佈到此隊列。當QThread :: exec()將讀取它時,它將停止進一步處理事件,退出無限循環並輕輕地終止該線程。
現在,你可能已經猜到,爲了收到終止消息,兩個條件必須滿足:
當人們從QThread子類化並使用自己的代碼覆蓋QThread :: run時,第一個通常會被違反。在大多數情況下,這是一種錯誤的用法,但它仍然被廣泛的教授和使用。在你的情況下,你似乎違反了第二個要求:你的代碼運行無限循環,因此QThread :: exec()根本沒有得到控制,也沒有任何機會檢查它是否需要退出。放棄你的回收站的無限循環,QThread :: exec()已經在爲你運行這樣的循環。想想如何重新編寫代碼,使其不會運行無限循環,這總是可能的。用「消息到線程」的概念來思考你的程序。如果您定期檢查某些東西,請創建一個QTimer,它將消息發送到您的對象並在您的插槽中執行檢查。如果處理大量數據,請將這些數據分割爲較小的塊並寫入對象,以便在某個時間響應某個消息,一次處理一個塊。例如。如果您正在逐行處理圖像,請創建一個插槽processLine(int line)並將一系列信號「0,1,2 ... height-1」發送到該插槽。請注意,您還必須在完成處理後顯式調用QThread :: quit(),因爲事件循環是無限的,當您處理圖像的所有行時,它不會「知道」。另外考慮使用QtConcurrent用於QThread的計算密集型任務。
現在,QThread :: terminate()以一種非常不同的方式停止線程。它只是要求操作系統殺死你的線程。操作系統會簡單地在代碼中的任意位置突然停止線程。線程堆棧內存將被free'd,但任何內存這個堆棧指向不會。如果線程擁有一些資源(如文件或互斥體),它永遠不會釋放它。涉及將數據寫入存儲器的操作可以在中間停止,並且使存儲器塊(例如對象)不完全填充並且處於無效狀態。正如你可能從這個描述中猜到的那樣,你永遠不應該調用:: terminate(),除非極少數情況下,保持線程運行比獲取內存資源泄漏更差。
QThread :: wait()只是一個方便的函數,一直等到QThread停止執行。它將與exit()和terminate()一起工作。
你也可以從QThread實現自己的子類的線程系統,並實現你自己的線程終止過程。所有你需要退出一個線程,實質上,只是在QThread :: run()必須返回的時候返回,並且你不能爲此使用exit()和terminate()。創建您自己的同步原語並使用它來指示您的代碼返回。但在大多數情況下,這不是一個好主意,請記住(除非您自己使用QEventLoop),Qt信號和插槽在這種情況下將無法正常工作。
關於'terminate':_「警告:這個函數是危險的,它的使用是不鼓勵的,線程可以在其代碼路徑的任何一點被終止,線程可以在修改數據時被終止,線程沒有機會自行清理,解鎖任何持有的互斥鎖等。總之,只有在絕對必要時才使用此功能。「_ source:http://doc.qt.io/qt-4.8/qthread.html#terminate。其餘的文件中你不明白的是什麼? –
是的,我知道這是危險的,這就是爲什麼我想知道如何正確地停止線程。 – iAmoric
在文檔中,似乎這兩個方法(帶有exit())都告訴線程循環退出。我真的沒有看到差異 – iAmoric