在Qt使用moveToThread() qt的線程

筆記:

使用中:子線程要向主線程發送 QMap<QString, QString> 類型的變量

子線程中:

QMap<QString, QString> testMap; 
emit  testSignal(testMap);

主線程中沒有收到該信號,并有如下信息:

QObject::connect: Cannot queue arguments of type 'QMap<QString,QString>'
(Make sure 'QMap<QString,QString>' is registered using qRegisterMetaType().)

解決方案:
在主界面構造函數中加入以下代碼:

qRegisterMetaType<QMap<QString, QString>>("QMap<QString, QString>");


出處

以下我將分享我的一些淺薄的對moveToThread()的使用心得。

使用線程有兩種方法:

一、

平時我們使用線程的時候一般是繼承QThread,實現它的run()函數,將需要在線程執行的代碼放在run()里邊運行。

{  
    while(bRun)//如果需要退出線程就將bRun設置為false.  
    {  
        qDebug()<<"run thread ID = "<<QThread::currentThreadId();  
        QThread::usleep(0);//usleep的值設置為0一樣會占滿cpu,但是根據老大測試,并不會使程序變卡。你也可以設置為10.  
    }  
    //  this->exec();//沒加這個的話線程就會結束,并發出Finsh()信號  
}  

如果使用這一方法,QThread::quit()沒有效果。因為這個線程根本就不需要事件循環。這種情況想退出,將bRun設置為false或者直接使用QT很不推薦的terminate().

二、使用moveToThread(),因為在Qt4.3(包括)之前,run 是虛函數,必須子類化QThread來實現run函數。而從Qt4.4開始run() 默認調用 QThread::exec() ,線程在調用quit()、exit()或terminat()之前不會退出。這樣一來不需要子類化 QThread 了,只需要子類化一個 QObject 就夠了,這正是被 Bradley T. Hughes(Qt的開發人員)推薦的方法。怎么用呢,使用connect()!!所以下邊要了解信號和槽的關系。等下會分析下connnect的第五個參數。對了,如果moveToThread里執行的函數沒執行完,你是無法通過quit來結束的,必須使用第一種方法:最歹毒的一招mthread->terminate()強制退出。

[cpp] view plain copy

class MyMoveToThreadFunc :public QObject
{
Q_OBJECT
public:
void showObjectThreadID()
{
qDebug()<<"# MyMoveToThreadFunc thread id = "<<QThread::currentThreadId();
}
signals:
void again();
public slots:
void slotOfThread()
{
qDebug()<<" MyMoveToThreadFunc slot thread id = "<<QThread::currentThreadId();
emit again();
}
};

class MyTry:public QObject
{
Q_OBJECT
public:
MyTry();
QThread *mThread;
MyMoveToThreadFunc *mFunc;
};

[cpp] view plain copy

MyTry::MyTry()
{
mThread = new QThread();
qDebug()<<"main thread id = "<<QThread::currentThreadId();
mFunc = new MyMoveToThreadFunc();
mFunc->moveToThread(mThread);</span>
QObject::connect(mThread,SIGNAL(started()),mFunc,SLOT(slotOfThread()));//slot將會在mThread中運行
mFunc->showObjectThreadID()//在主程序運行。
mThread->start();//啟動線程
}

如果要實現事件循環怎么辦?一樣,隨便找個信號連接到slotOfThread(),循環發送就行了。例如,你重載mThread,讓他以第一種循環循環發出信號給mFunc連接也行。記住,直接在主程序調用mFunc的函數,函數還是會是在主程序運行。在這啰嗦一句,子類化QThread的子類,只有在run()函數里才是屬于線程。所以有時候你在子類構造函數創建的實例是不屬于線程創建的,有時候就會提示這種: QObject::startTimer: Timers can only be used with threads started with QThread 。(我還沒測試,別人發的問題認為是這個)。

現在我們來分析下connect()的五個參數。先吃飯,可能明天寫完。
有六種參數:
1
2
3
4
5
6

Qt::AutoConnection

Qt::DirectConnection

Qt::QueuedConnection

Qt::
BlockingQueuedConnection
Qt::UniqueConnection

Qt::AutoCompatConnection

這里面一共有六種方式。
前兩種比較相似,都是同一線程之間連接的方式,不同的是Qt::AutoConnection是系統默認的連接方式。這種方式連接的時候,槽不是馬上被執行的,而是進入一個消息隊列,待到何時執行就不是我們可以知道的了,當信號和槽不是同個線程,會使用第三種QT::QueueConnection的鏈接方式。如果信號和槽是同個線程,調用第二種Qt::DirectConnection鏈接方式。
第二種Qt::DirectConnection是直接連接,也就是只要信號發出直接就到槽去執行,無論槽函數所屬對象在哪個線程,槽函數都在發射信號的線程內執行,一旦使用這種連接,槽將會不在線程執行!。
第三種Qt::QueuedConnection和第四種Qt::BlockingQueuedConnection是相似的,都是可以在不同進程之間進行連接的,不同的是,這里第三種是在對象的當前線程中執行,并且是按照隊列順序執行。當當前線程停止,就會等待下一次啟動線程時再按隊列順序執行 ,等待QApplication::exec()或者線程的QThread::exec()才執行相應的槽,就是說:當控制權回到接受者所依附線程的事件循環時,槽函數被調用,而且槽函數在接收者所依附線程執行,使用這種連接,槽會在線程執行。
第四種Qt::BlockingQueuedConnection是(必須信號和曹在不同線程中,否則直接產生死鎖)這個是完全同步隊列只有槽線程執行完才會返回,否則發送線程也會等待,相當于是不同的線程可以同步起來執行。
第五種Qt::UniqueConnection跟默認工作方式相同,只是不能重復連接相同的信號和槽;因為如果重復鏈接就會導致一個信號發出,對應槽函數就會執行多次。
第六種Qt::AutoCompatConnection是為了連接QT4 到QT3的信號槽機制兼容方式,工作方式跟Qt::AutoConnection一樣。顯然這里我們應該選擇第三種方式,我們不希望子線程沒結束主線程還要等,我們只是希望利用這個空閑時間去干別的事情,當子線程執行完了,只要發消息給主線程就行了,到時候主線程會去響應。

后記

為什么要使用moveToTread()呢。
eg:moveToThread對比傳統子類化Qthread更靈活,僅需要把你想要執行的代碼放到槽,movetothread這個object到線程,然后拿一個信號連接到這個槽就可以讓這個槽函數在線程里執行。可以說,movetothread給我們編寫代碼提供了新的思路,當然不是說子類化qthread不好,只是你應該知道還有這種方式去調用線程。
老大認為,輕量級的函數可以用movethread,多個短小精悍能返回快速的線程函數適用 ,無需創建獨立線程類,例如你有20個小函數要在線程內做, 全部扔給一個QThread。而我覺得movetothread和子類化QThread的區別不大,更可能是使用習慣引導。又或者你一開始沒使用線程,但是后邊發覺這些代碼還是放線程比較好,如果用子類化QThread的方法重新設計代碼,將會有可能讓你把這一段推到重來,這個時候,moveThread的好處就來了,你可以把這段代碼的從屬著movetothread,把代碼移到槽函數,用信號觸發它就行了。其它的話movetothread它的效果和子類化QThread的效果是一樣的,槽就相當于你的run()函數,你往run()里塞什么代碼,就可以往槽里塞什么代碼,子類化QThread的線程只可以有一個入口就是run(),而movetothread就有很多觸發的入口。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,660評論 25 708
  • 由于文章長度限制,本文作為[譯]線程編程指南(一)后續部分。 Run Loops Run loop是與線程相關的基...
    巧巧的二表哥閱讀 1,202評論 0 5
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,719評論 18 399
  • 以太網 令牌環網 FDDI(光纖分布式數據接口) RS-232串行線路作用: 為IP模塊發送和接收IP數據報 為A...
    我不是板板閱讀 261評論 0 0
  • 這次把大寶小寶全權委托給媽媽了,單槍匹馬去城里了,主要的任務就是看看有沒合適的房源訂一套下來,是這次任務的重中之重...
    紅豬豬閱讀 356評論 0 1