Qt跨線程調用錯誤解析及解決辦法


錯誤提示:Error: Cannot create children for a parent that is in a different thread.

錯誤案例分析

新建SerialLink子線程,繼承QThread,並重寫它的run(),調用 start()函數時自動調用重載的run()函數。在主線程中創建SerialLink類的對象。

串口_port在SerialLink的頭文件中定義,在_hardwareConnect()函數中初始化。在_connect()函數中調用start()函數啟動線程,自動調用重載的run()函數。

 

Class SerialLink: public QThread
{ 
……
QSerialPort* _port;
 ……	
}

void SerialLink:: _hardwareConnect( )
{
……
_port = new SerialPort( );
……
}

void SerialLink:: _connect( )
{
……
_hardwareConnect( );
start( );
……
}

void SerialLink:: run( )
{
……
}

  該錯誤是跨線程調用引起的。

      原因:_port的初始化是在SerialLink類中,SerialLink子線程是在主線程中創建的子線程,在SerialLink對象本身工作在主線程下,其中定義的所有東西都屬於創建SerialLink的線程,即主線程,所以_port應該是屬於主線程(父線程)的;只有run()范圍內的代碼工作在次線程中,所以在SerialLink的run()中調用_port屬於跨線程調用,就會出現異常。

      解決辦法:_portrun函數中初始化,_port就是在同一子線程中創建和調用,不會出現跨線程調用錯誤。

void SerialLink* run( )
{
_hardwareConnect( );
……
}
void SerialLink* _connect( )
{
……
start( );
……
}
void _hardwareConnect( )
{
……
_port = new SerialPort( );
……
}

總結

Thread對象本身工作在主線程下,即使調用其定義的變量和方法,也是工作在主線程下,只有run()范圍內的代碼才工作在子線程中。為避免跨線程調用引起異常,一個對象的創建和調用要放在同一線程中。

推薦的工作方式:利用Qt的事件驅動特性,將需要在次線程中處理的業務放在獨立的模塊(類)中,由主線程創建完該對象后,將其移交給指定的線程,且可以將多個類似的對象移交給同一個線程。

connect連接類型:

 1) 自動連接(AutoConnection),默認的連接方式,如果信號與槽,也就是發送者與接受者在同一線程,等同於直接連接;如果發送者與接受者處在不同線程,等同於隊列連接。

2) 直接連接(DirectConnection),當信號發射時,槽函數立即直接調用。無論槽函數所屬對象在哪個線程,槽函數總在發送者所在線程執行。

3) 隊列連接(QueuedConnection),當控制權回到接受者所在線程的事件循環時,槽函數被調用。槽函數在接受者所在線程執行。

在GUI程序中,主線程也叫GUI線程,因為它是唯一被允許執行GUI相關操作的線程。對於一些耗時的操作,如果放在主線程中,就會出現界面無法響應的問題。這種問題的一種解決方式是,把這些耗時操作放到子線程中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM