国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

解析Qt中QThread使用方法

移動開發
本文介紹了Qt中QThread使用方法,在本片文章中反復提到了線程的使用,詳細內容請參考本文,QThread的使用方法:#include <qthread.h>繼承了Qt。

本文講述的是在QtQThread使用方法,QThread似乎是很難的一個東西,特別是信號和槽,有非常多的人(盡管使用者本人往往不知道)在用不恰當(甚至錯誤)的方式在使用 QThread,隨便用google一搜,就能搜出大量結果出來。無怪乎Qt的開發人員 Bradley T. Hughes 聲嘶力竭地喊you are-doing-it-wrong

和眾多用戶一樣,初次看到這個時,感到 Bradley T. Hughes有 些莫名奇妙,小題大作。盡管不舒服,當時還是整理過一篇博客QThread 的使用方法

時間過去3個月,盡管依然沒怎么用thread;但今天csdn論壇中有人問到這個問題,想想還是盡我所能整理一下吧。提升自己,方便他人,何樂而不為呢?

QThread東西還是比較多的,而且我對底層對象了解有限,僅就一點進行展開(或許是大家最關心的一點):QThread中的slots在那個線程中執行?

QThread::run

run 函數是做什么用的?Manual中說的清楚:

run 對于線程的作用相當于main函數對于應用程序。它是線程的入口,run的開始和結束意味著線程的開始和結束。 原文如下:

  1. The run() implementation is for a thread what the main()   
  2. entry point is for the application. All code executed in a call stack that starts in the run()   
  3. function is executed by the new thread, and the thread finishes when the function returns.  

這么短的文字一眼就看完了,可是,這是什么意思呢?又能說明什么問題呢?看段簡單代碼:

  1. class Thread:public QThread {       
  2. Q_OBJECT public:       
  3. Thread(QObject* parent=0):QThread(parent){}   
  4. public slots:       
  5. void slot() { ... } signals:       
  6. void sig(); protected:       
  7. void run() { ...} };    
  8. int main(int argc, char** argv) { ...     Thread thread; ... } 

對照前面的定理,run函數中的代碼時確定無疑要在次線程中運行的,那么其他的呢?比如 slot 是在次線程還是主線程中運行?

QObject::connect

涉及信號槽,我們就躲不過 connect 函數,只是這個函數大家太熟悉。我不好意思再用一堆廢話來描述它,但不說又不行,那么折中一下,只看它的***一個參數吧(為了簡單起見,只看它最常用的3個值):

1、自動連接(Auto Connection)

這是默認設置

如果發送者和接收者處于同一線程,則等同于直接連接

如果發送者和接受者位于不同線程,則等同于隊列連接

也就是這說,只存在下面兩種情況

2、直接連接(Direct Connection)

當信號發射時,槽函數將直接被調用。

無論槽函數所屬對象在哪個線程,槽函數都在發射者所在線程執行。

3、隊列連接(Queued Connection)

當控制權回到接受者所在線程的事件循環式,槽函數被調用。

槽函數在接收者所在線程執行。

同前面一樣,這些文字大家都能看懂。但含義呢?

不妨繼續拿前面的例子來看,slot 函數是在主線程還是次線程中執行呢?

定理二強調兩個概念:發送者所在線程 和 接收者所在線程。而 slot 函數屬于我們在main中創建的對象 thread,即thread屬于主線程

隊列連接告訴我們:槽函數在接受者所在線程執行。即 slot 將在主線程執行

直接連接告訴我們:槽函數在發送者所在線程執行。發送者在那個線程呢??不定!

自動連接告訴我們:二者不在同一線程時,等同于隊列連接。即 slot 在主線程執行

要徹底理解這幾句話,你可能需要看Qt meta-object系統和Qt event系統)

如果上兩節看不懂,就記住下面的話吧(自己總結的,用詞上估計會不太準確)。

QThread 是用來管理線程的,它所處的線程和它管理的線程并不是同一個東西

QThread 所處的線程,就是執行 QThread t(0) 或 QThread * t=new QThread(0) 的線程。也就是咱們這兒的主線程

QThread 管理的線程,就是 run 啟動的線程。也就是次線程

因為QThread的對象在主線程中,所以他的slot函數會在主線程中執行,而不是次線程。除非:QThread 對象在次線程中

slot 和信號是直接連接,且信號所屬對象在次線程中

但上兩種解決方法都不好,因為QThread不是這么用的(Bradley T. Hughes)

好了,不在添加更多文字了,看代碼,估計咱們都會輕松點

主線程(信號)QThread(槽)

這是Qt Manual 和 例子中普遍采用的方法。 但由于manual沒說槽函數是在主線程執行的,所以不少人都認為它應該是在次線程執行了。

定義一個 Dummy 類,用來發信號

定義一個 Thread 類,用來接收信號

重載 run 函數,目的是打印 threadid

  1. /*!  
  2. * \file main.cpp  
  3. *  
  4. * Copyright (C) 2010, dbzhang800  
  5. * All rights reserved.  
  6. *  
  7. */  
  8. #include <QtCore/QCoreApplication>   
  9. #include <QtCore/QObject>   
  10. #include <QtCore/QThread>   
  11. #include <QtCore/QDebug>  class Dummy:public QObject {       
  12. Q_OBJECT public:     
  13. Dummy(){} public slots:  void emitsig()   
  14. {         emit sig();       
  15. } signals:     void sig();   
  16. };    
  17. class Thread:public QThread {      
  18.  Q_OBJECT public:       
  19. Thread(QObject* parent=0):QThread(parent) {   //moveToThread(this); }   
  20. public slots:     void slot_main()     {           
  21. qDebug()<<"from thread slot_main:" <<currentThreadId();       
  22. } protected:     void run()     {           
  23. qDebug()<<"thread thread:"<<currentThreadId();           
  24. exec();       
  25. }   
  26. };   
  27. #include "main.moc" int main(int argc, char *argv[]) {       
  28.  QCoreApplication a(argc, argv);       
  29. qDebug()<<"main thread:"<<QThread::currentThreadId();      
  30.  Thread thread;       
  31. Dummy dummy;      
  32.  QObject::connect(&dummy, SIGNAL(sig()), &thread, SLOT(slot_main()));       
  33. thread.start();      
  34.  dummy.emitsig();       
  35. return a.exec(); } 

然后看到結果(具體值每次都變,但結論不變)

  1. main thread: 0x1a40 from thread slot_main: 0x1a40 thread thread: 0x1a48 

看到了吧,槽函數的線程和主線程是一樣的!

如果你看過Qt自帶的例子,你會發現 QThread 中 slot 和 run 函數共同操作的對象,都會用QMutex鎖住。為什么?因為slot和run處于不同線程,需要線程間的同步!

如果想讓槽函數slot在次線程運行(比如它執行耗時的操作,會讓主線程死掉),怎么解決呢?

注意:發送dummy信號是在主線程, 接收者 thread 也在主線程中。 參考我們前面的結論,很容易想到: 將 thread 放到次線程中不就行了 這也是代碼中注釋掉的 moveToThread(this)所做的,去掉注釋,你會發現slot在次線程中運行

  1. main thread: 0x13c0 thread thread: 0x1de0 from thread slot_main: 0x1de0 

這可以工作,但這是 Bradley T. Hughes 強烈批判的用法。推薦的方法后面會給出。

#p#

run中信號與QThread中槽

定義一個 Dummy 類,在run中發射它的信號

也可以在run中發射 Thread 中的信號,而不是Dummy(效果完全一樣),QThread 定義槽函數,重載run函數
 

  1. /*!  
  2. * \file main.cpp  
  3. *  
  4. * Copyright (C) 2010, dbzhang800  
  5. * All rights reserved.  
  6. *  
  7. */  
  8. #include <QtCore/QCoreApplication>   
  9. #include <QtCore/QObject>   
  10. #include <QtCore/QThread>   
  11. #include <QtCore/QDebug>    
  12. class Dummy:public QObject {       
  13. Q_OBJECT public:     Dummy(QObject* parent=0):QObject(parent){}   
  14. public slots: oid emitsig()       
  15. {  emit sig();    
  16. } signals:     void sig(); };    
  17. class Thread:public QThread {       
  18. Q_OBJECT public:      
  19. Thread(QObject* parent=0):QThread(parent) { //moveToThread(this); }   
  20. public slots:     void slot_thread()     {           
  21. qDebug()<<"from thread slot_thread:" <<currentThreadId();     }   
  22. signals:     void sig(); protected:     void run()     {           
  23. qDebug()<<"thread thread:"<<currentThreadId();          
  24.  Dummy dummy;           
  25. connect(&dummy, SIGNAL(sig()), this, SLOT(slot_thread()));          
  26.  dummy.emitsig();         e  
  27. xec();       
  28. }   
  29. };    
  30. #include "main.moc"  int main(int argc, char *argv[]) {       
  31. QCoreApplication a(argc, argv);       
  32. qDebug()<<"main thread:"<<QThread::currentThreadId();       
  33. Thread thread;       
  34. thread.start();       
  35. return a.exec(); } 

想看結果么?

  1. main thread: 0x15c0 thread thread: 0x1750 from thread slot_thread: 0x15c0 

其實沒懸念,肯定是主線程

thread 對象本身在主線程。所以它的槽也在要在主線程執行,如何解決呢?

(方法一)前面提了 moveToThread,這兒可以用,而且可以解決問題。當同樣,是被批判的對象。
 
(方法二)注意哦,這兒我們的信號時次線程發出的,對比connect連接方式,會發現:

采用直接連接,槽函數將在次線程(信號發出的線程)執行

這個方法不太好,因為你需要處理slot和它的對象所在線程的同步。需要 QMutex 一類的東西

推薦的方法,其實,這個方法太簡單,太好用了。定義一個普通的QObject派生類,然后將其對象move到QThread中。使用信號和槽時根本不用考慮多線程的存在。也不用使用QMutex來進行同步,Qt的事件循環會自己自動處理好這個。

  1. /*!  
  2. * \file main.cpp  
  3. *  
  4. * Copyright (C) 2010, dbzhang800  
  5. * All rights reserved.  
  6. *  
  7. */  
  8. #include <QtCore/QCoreApplication>   
  9. #include <QtCore/QObject>   
  10. #include <QtCore/QThread>   
  11. #include <QtCore/QDebug>    
  12. class Dummy:public QObject {       
  13. Q_OBJECT   
  14. public:     Dummy(QObject* parent=0):QObject(parent)     {}   
  15. public slots:     void emitsig()     {         emit sig();       
  16. } signals:     void sig(); };    
  17. class Object:public QObject {       
  18. Q_OBJECT   
  19. public: Object(){} public slots:void slot() {    
  20. qDebug()<<"from thread slot:" <<QThread::currentThreadId();       
  21. }   
  22. };    
  23. #include "main.moc"  int main(int argc, char *argv[]) {      
  24.  QCoreApplication a(argc, argv);       
  25. qDebug()<<"main thread:"<<QThread::currentThreadId();      
  26.  QThread thread;       
  27. Object obj;       
  28. Dummy dummy;       
  29. obj.moveToThread(&thread);      
  30.  QObject::connect(&dummy, SIGNAL(sig()), &obj, SLOT(slot()));      
  31.  thread.start();       
  32. dummy.emitsig();       
  33. return a.exec(); } 

結果:恩,slot確實不在主線程中運行(這么簡單不值得歡呼么?)

  1. main thread: 0x1a5c from thread slot: 0x186c 

小結:QtQThread使用方法,講到這里。在本文中多次提到線程,那么對于QThread類,它提供了與系統無關的線程QThread代表在程序中一個單獨的線程控制,在多任務操作系統中,它和同一進程中的其它線程共享數據,但運行起來就像一個單獨的程序一樣。它不是在main()中開始,QThread是在run()中開始運行的。

【編輯推薦】

淺談Qt中多線程編程

解析 QT 靜態庫和動態庫

Qt中實現QThread線程同步QFtp

QT中關于信號與槽機制的實現原理

C#常用線程同步方法應用場景和實現原理

責任編輯:zhaolei 來源: 互聯網
相關推薦

2011-06-30 16:53:18

QT Creator TableWidge

2010-10-08 14:27:25

JavascriptSplit

2011-08-30 13:49:57

Qt數據庫QTableView

2011-06-24 15:06:40

QT

2013-06-08 17:09:35

Android開發移動開發XML解析

2011-06-14 09:46:11

Qt QThread 線程

2011-08-11 17:00:33

iPhone數據庫SQLite

2011-08-29 15:58:51

Lua函數

2011-07-04 14:29:25

Qt Designer 容器

2011-08-19 13:51:12

2010-08-09 10:16:01

FlexBuilder

2010-10-09 10:30:03

JS event

2011-08-23 09:44:28

LUA腳本

2009-11-25 10:02:27

PHP會話Sessio

2011-02-24 13:09:10

FireFTP

2012-01-13 09:55:54

jQuery

2011-08-10 16:08:02

iPhoneProtocol協議

2011-07-21 15:05:14

iPhone 數據庫

2011-06-09 15:47:01

Qt Visual Stu

2009-12-24 16:36:06

WPF InkCanv
點贊
收藏

51CTO技術棧公眾號

99久热re在线精品996热视频| 69成人精品免费视频| 福利一区在线观看| 日本一区二区成人在线| 亚洲一区二区三区四区的| 狠狠色噜噜狠狠狠狠97| 91精品国产色综合久久ai换脸| 亚洲国产成人91精品| 久久综合久久八八| 国产日韩在线视频| 444亚洲人体| 精品少妇一区二区三区在线| 男人午夜天堂| 黄页网站在线| 亚洲日产av中文字幕| 麻豆免费精品视频| 亚洲欧美另类久久久精品2019| 亚洲高清久久久久久| 国语自产在线不卡| 久久久精品动漫| 特级全黄一级毛片| 欧美极品免费| 亚洲网站在线| 亚洲黄色免费电影| 中文字幕日韩欧美在线| 麻豆精品蜜桃一区二区三区| 久久国产情侣| 国产伦精品一区二区三区高清版| 久久久久久久久久久久久国产精品 | 日本成人手机在线| 高清成人在线观看| 久久久久中文字幕| 日韩av成人| 男人的j进女人的j一区| 一区二区三区亚洲| 成人福利视频在| 亚洲人成伊人成综合图片| 精品久久久久久久久久国产| 国产精品自拍首页| av影院在线免费观看| 成人激情校园春色| 欧美高跟鞋交xxxxxhd| 午夜免费福利在线| 日本一区二区在线看| 7777精品伊人久久久大香线蕉超级流畅 | 激情五月婷婷综合| 99麻豆久久久国产精品免费| **欧美日韩在线| 欧洲亚洲精品久久久久| 日韩免费视频| 久久久国产精品不卡| 婷婷开心激情综合| 欧美精品成人91久久久久久久| 国产一二三四五| 羞羞的网站在线观看| av一区二区不卡| 成人午夜激情免费视频| 亚洲视频精品在线观看| 在线免费观看亚洲| 久久高清国产| 91麻豆精品国产91久久久久久久久 | 成人久久一区| 蜜桃av一区二区| 成人综合婷婷国产精品久久| 日韩片之四级片| 欧美一区二区三区四区在线| 无码人妻精品一区二区蜜桃网站| 欧美最顶级a∨艳星| 国产伦理一区| 精品中文字幕乱| 美女张开让男人捅| 成人激情视频| 91精品国产色综合久久ai换脸| youjizzxxxx18| 国产麻豆精品久久| 亚洲免费大片在线观看| 一道本成人在线| 91人成网站www| 亚洲综合在线网站| 日韩在线网址| 国产女人aaa级久久久级| 精品亚洲永久免费精品| 视频一区二区在线| 日本精品一区二区三区高清 久久| 国产视频九色蝌蚪| 色戒汤唯在线观看| 91在线精品秘密一区二区| 国产精品一区二区久久久久| 18video性欧美19sex高清| 亚洲黄色尤物视频| 黄黄视频在线观看| 亚洲精品一区二区妖精| 2018国产精品视频| 亚洲成人福利| 欧美成a人免费观看久久| 美女日韩在线中文字幕| 亚洲精品国产拍免费91在线| 国产高清一区视频| av电影在线观看一区二区三区| 一区二区黄色| 欧美日韩另类一区| 国产精品裸体瑜伽视频| 国产三级一区| 久久久久88色偷偷免费| 日本午夜一区二区三区| 999色成人| 国产亚洲视频系列| 亚洲成人黄色在线观看| 黄色大片在线免费看| 国产精品白丝av嫩草影院| 一区二区三区高清在线| 国产精品天天狠天天看| 性欧美猛交videos| 亚洲日本韩国一区| 国产一区二区精品免费| 国产天堂在线播放视频| 不卡一区在线观看| 精品不卡在线| 乱亲女h秽乱长久久久| 色偷偷888欧美精品久久久| 日本无删减在线| 欧美午夜在线一二页| 九色porn| 综合久久久久综合| 日av中文字幕| 国产成人精品亚洲777人妖| 成人黄色片在线| 精品久久精品| 欧美一级视频一区二区| 亚洲国产日韩欧美在线99| 国产成人l区| 精品久久久久久久中文字幕| 欧美s码亚洲码精品m码| 国产日韩亚洲欧美综合| 成人性生交免费看| 一区二区激情小说| 中文字幕在线视频免费观看| 国产欧美精品在线观看| 国产美女被遭强高潮免费网站| 久久亚洲综合av| 国产国产国产国产国产国产| 国产精品一区二区在线观看不卡| 欧美另类高清视频在线| 蜜臀av性久久久久av蜜臀妖精| 日本女人高潮视频| 成人免费不卡视频| 天天干天天玩天天操| 久久久久久久久岛国免费| caoporen人人| 欧美一级xxx| 少妇一级淫免费播放| 国产精品进线69影院| 污视频在线观看免费| av男人天堂一区| 欧美高清xxxxxkkkkk| 精品日韩美女的视频高清| 97超碰资源站在线观看| 一区二区三区亚洲| 国产一区精品二区| 日本一区二区三区在线播放| 日韩视频一区| 国产极品粉嫩福利姬萌白酱 | 亚洲综合精品自拍| 国产黄色小视频在线| 少妇久久久久久| 青青草成人影院| 女女同性女同一区二区三区按摩| 国产精品久99| 性国产高清在线观看| 2021久久精品国产99国产精品| 中文视频一区| 天堂一区在线观看| 亚洲国产成人精品女人久久久 | caoporm免费视频在线| 日韩中文在线中文网三级| 狠狠色狠狠色综合婷婷tag| 欧美人与物videos另类| 亚洲色图视频免费播放| av大全在线| 97在线视频免费| 久久人人精品| 黄网在线播放| 色婷婷综合久久久久中文字幕1| 影音先锋久久精品| 亚欧精品一区| 国产亚洲精品日韩| 在线日韩欧美| 欧美13~18sex性hd| 希岛爱理av一区二区三区| 国产欧美123| 一区二区三区日韩在线观看| 日韩脚交footjobhd| 国产精品男人爽免费视频1| 国产精品一区免费视频| 超碰在线caoporen| av一区二区三区免费| 久久综合久久综合九色| 大地资源网3页在线观看| 91丝袜脚交足在线播放| 亚洲综合色视频|