自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

QT核心編程之Qt線程 (3)

移動(dòng)開發(fā)
Qt對(duì)線程提供了支持,它引入了一些基本與平臺(tái)無(wú)關(guān)的線程類、線程安全傳遞事件的方式和全局Qt庫(kù)互斥量允許你從不同的線程調(diào)用Qt的方法。

QT核心編程之Qt線程是本節(jié)要介紹的內(nèi)容,QT核心編程我們要分幾個(gè)部分來介紹,想?yún)⒖几鄡?nèi)容,請(qǐng)看末尾的編輯推薦進(jìn)行詳細(xì)閱讀,先來看本篇內(nèi)容。

Qt對(duì)線程提供了支持,它引入了一些基本與平臺(tái)無(wú)關(guān)的線程類、線程安全傳遞事件的方式和全局Qt庫(kù)互斥量允許你從不同的線程調(diào)用Qt的方法。Qt中與線程應(yīng)用相關(guān)的類如表6所示。

QT核心編程之Qt線程 

表6 Qt中與線程相關(guān)的類

使用線程需要Qt提供相應(yīng)的線程庫(kù)的支持,因此,在編譯安裝Qt時(shí),需要加上線程支持選項(xiàng)。

當(dāng)在Windows操作系統(tǒng)上編譯Qt時(shí),線程支持是在一些編譯器上的一個(gè)選項(xiàng)。在Windows操作系統(tǒng)上編譯應(yīng)用程序時(shí),通過在qconfig.h文件中增加一個(gè)選項(xiàng)來解決來解決這個(gè)問題。

在Mac OS X和Unix上編譯Qt時(shí),你應(yīng)在運(yùn)行configure腳本時(shí)添加-thread選項(xiàng)。在Unix平臺(tái)上,多線程程序必須用特殊的線程支持庫(kù)連接,多線程程序必須連接線程支持庫(kù)libqt-mt,而不是標(biāo)準(zhǔn)的Qt庫(kù)。編譯應(yīng)用程序時(shí),你應(yīng)該使用宏定義QT_THREAD_SUPPORT來編譯(如:編譯時(shí)使用-DQT_THREAD_SUPPORT)。

1、線程類QThread

在 Qt中提供了QThread線程類,它提供了創(chuàng)建一個(gè)新線程的方法。線程通過重載 QThread::run()函數(shù)開始執(zhí)行的,這一點(diǎn)與Java中的線程類相似。

示例1:一個(gè)簡(jiǎn)單的線程

下面的例子實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的繼承自QThread的用戶線程類,并運(yùn)行2個(gè)線程,線程b在線程a運(yùn)行完后運(yùn)行。代碼列出如下:

  1. class MyThread : public QThread {  
  2. public:    virtual void run();  
  3. };  
  4.  void MyThread::run()   //運(yùn)行線程{  
  5.     for( int count = 0;  
  6.  count < 20; count++ ) {  
  7.         sleep( 1 );  
  8.         qDebug( "Ping!" );  
  9.     }  
  10. }   
  11. int main(){   
  12.    MyThread a;  
  13.     MyThread b;  
  14.     a.start(); //通過調(diào)用run()函數(shù)來執(zhí)行  
  15.     b.start();  
  16.     a.wait();  
  17.     b.wait();  

只有一個(gè)線程類是不夠的,對(duì)于支持多線程的程序來說,還需要保護(hù)兩個(gè)不同的線程對(duì)數(shù)據(jù)的同時(shí)訪問,因此 Qt 提供了QMutex 類,一個(gè)線程可以鎖住互斥量,當(dāng)互斥量被鎖住時(shí),將阻塞其它線程訪問臨界數(shù)據(jù),直到這個(gè)線程釋放互斥量。這樣,可以保護(hù)臨界數(shù)據(jù)一次只能被一個(gè)線程訪問。

Qt庫(kù)互斥量(qApp->lock()和qApp->unlock())是在訪問Qt的GUI界面資源時(shí)用到的互斥量。在 Qt中沒有使用互斥量而調(diào)用一個(gè)函數(shù)通常會(huì)導(dǎo)致不可預(yù)知的行為。從另外一個(gè)線程中調(diào)用Qt的一個(gè)GUI相關(guān)函數(shù)需要使用Qt庫(kù)互斥量。在這種情況下,所有訪問圖形或窗口系統(tǒng)資源的函數(shù)都與GUI相關(guān)。如果對(duì)象僅被一個(gè)線程訪問,使用容器類,字符串或者輸入/輸出類不需要任何互斥量。

2、線程安全的事件傳遞

在Qt中,一個(gè)線程總是一個(gè)事件線程,線程從窗口系統(tǒng)中拉出事件并且把它們分發(fā)給窗口部件。靜態(tài)方法QThread::postEvent從線程中郵遞事件,而不是從事件線程。事件線程被喚醒并且事件象一個(gè)正常窗口系統(tǒng)的事件一樣在事件線程中被分發(fā)。例如,你可以從不同的線程強(qiáng)制一個(gè)窗口部件進(jìn)行重繪,方法如下:

  1. QWidget *mywidget;QThread::postEvent( mywidget, new QPaintEvent( QRect(0, 0, 100, 100) ) ); 

上述代碼將異步地使mywidget在它區(qū)域中重繪一塊100*100的正方形區(qū)域。

另外,還需要一些機(jī)制使得處于等待狀態(tài)的線程在給定條件下被喚醒。QWaitCondition 類就提供了這種功能。線程等待的條件QWaitCondition滿足,QWaitCondition表明發(fā)生了什么事情,它阻塞直到這件事情發(fā)生。當(dāng)發(fā)生給定的事情時(shí),QWaitCondition 將喚醒等待該事情的所有線程或者喚醒任意一個(gè)被選中的線程。(這和POSIX線程條件變量具有相同功能,是Unix上的一種實(shí)現(xiàn)。)

示例2:QWaitCondition類應(yīng)用

下面這個(gè)例子的功能是:當(dāng)你按下按鈕,這個(gè)程序就會(huì)喚醒worker線程,這個(gè)線程在按鈕上顯示工作狀態(tài):等待(Waiting)還是正在工作(Working)。當(dāng)按鈕被按下時(shí),worker線程正在工作,那么對(duì)線程不產(chǎn)生影響。當(dāng)run函數(shù)再次循環(huán)到mycond.wait()時(shí),線程阻塞并等待。當(dāng)按鈕再被按下時(shí),觸發(fā)slotClicked()函數(shù)運(yùn)行,喚醒等待的線程。

  1. #include <qapplication.h> 
  2. #include <qpushbutton.h> // 全局條件變量  
  3. QWaitCondition mycond; // Worker類實(shí)現(xiàn)  
  4. class Worker : public QPushButton, public QThread{  
  5.     Q_OBJECT public:    Worker(QWidget *parent = 0, const char *name = 0) : QPushButton(parent, name) {   
  6.        setText("Start Working");         // 將QPushButton繼承來的信號(hào)與槽slotClicked()連接起來  
  7.         connect(this, SIGNAL(clicked()), SLOT(slotClicked()));         // 調(diào)用從QThread繼承來的start()方法開始線程的執(zhí)行   
  8.        QThread::start();  
  9.     }  
  10.  public slots:    void slotClicked()  {   // 喚醒等待這個(gè)條件變量的一個(gè)線程   
  11.        mycond.wakeOne();  
  12.     }   
  13. protected:    void run() //重載run函數(shù)    {   
  14.          while ( TRUE ) {            // 鎖定應(yīng)用程序互斥鎖,并且設(shè)置窗口標(biāo)題來表明我們正在等待開始工作  
  15.             qApp->lock();  
  16.             setCaption( "Waiting" );  
  17.             qApp->unlock();             // 等待直到我們被告知可以繼續(xù)   
  18.            mycond.wait();            // 如果到了這里,表示我們已經(jīng)被另一個(gè)線程喚醒   
  19.            qApp->lock();  
  20.             setCaption( "Working!" );// 設(shè)置標(biāo)題,表示正在工作   
  21.            qApp->unlock();   
  22.      }  
  23.     }  
  24. };   
  25. int main( int argc, char **argv ){  
  26.     QApplication app( argc, argv );     // 創(chuàng)建一個(gè)worker  
  27.     Worker firstworker( 0, "worker" );  
  28.      app.setMainWidget( &worker ); //將worker設(shè)置為應(yīng)用程序的主窗口  
  29.     worker.show();    
  30.    return app.exec();  

當(dāng)進(jìn)行線程編程時(shí),需要注意的一些事項(xiàng):

(1)在持有Qt庫(kù)互斥量時(shí)不要做任何阻塞操作。這將凍結(jié)事件循環(huán)。

(2)確認(rèn)你鎖定一個(gè)遞歸QMutex的次數(shù)等于解鎖的次數(shù),不能多也不能少。

(3)在調(diào)用除了Qt容器和工具類外的任何東西之前鎖定Qt應(yīng)用程序互斥量。

(4)謹(jǐn)防隱含的共享類,如果你需要在線程之間指定它們,你應(yīng)該用detach()分離它們。

(5)小心沒有被設(shè)計(jì)成線程安全的Qt類,例如,QPtrList的API接口不是線程安全的,并且如果不同的線程需要遍歷一個(gè)QPtrList,它們應(yīng)該在調(diào)用QPtrList::first()之前鎖住,在到達(dá)終點(diǎn)后解鎖。

(6)確信僅在GUI線程中創(chuàng)建繼承自QWidget、QTimer和QSocketNotifier的對(duì)象。在一些平臺(tái)上,創(chuàng)建在線程中而不是GUI線程的對(duì)象永遠(yuǎn)不會(huì)接收到底層窗口系統(tǒng)的事件。

(7)和上面很相似,只在GUI線程中使用QNetwork類。因?yàn)樗械腝Network類都是異步的,沒必要把QSocket用在多線程中。

(8)永遠(yuǎn)不要嘗試在不是GUI線程線程中調(diào)用processEvents()函數(shù)。這也包括QDialog::exec()、QPopupMenu::exec()、QApplication::processEvents()和其它一些函數(shù)。

(9)在你的應(yīng)用程序中,不要把普通的Qt庫(kù)和支持線程Qt庫(kù)混合使用。這意味著如果你的程序使用了支持線程Qt庫(kù),你就不能連接普通的Qt庫(kù)、動(dòng)態(tài)的載入普通Qt庫(kù)或者動(dòng)態(tài)地連接其它依賴普通Qt庫(kù)的庫(kù)或者插件。在一些系統(tǒng)上,這樣做會(huì)導(dǎo)致Qt庫(kù)中使用的靜態(tài)數(shù)據(jù)崩潰。

小結(jié):QT核心編程之Qt線程 的內(nèi)容介紹完了,希望本節(jié)內(nèi)容隨你有所幫助,如果需要更多資料請(qǐng)參考編輯推薦。

【編輯推薦】

QT核心編程之Qt模板庫(kù)(1)

QT核心編程之集合類 (2)

QT核心編程之鼠標(biāo)拖放 (4)

QT核心編程之鍵盤焦點(diǎn) (5)

QT核心編程之會(huì)話管理 (6)

QT核心編程之調(diào)試技術(shù) (7)

責(zé)任編輯:zhaolei 來源: 互聯(lián)網(wǎng)
相關(guān)推薦

2011-06-22 09:40:32

QT 模板庫(kù) 模板

2011-06-22 10:39:56

QT 會(huì)話管理

2011-06-22 10:27:32

QT 鍵盤 焦點(diǎn)

2011-06-22 09:58:04

QT 集合類

2011-06-22 10:20:11

QT 鼠標(biāo) 拖放

2011-06-22 10:45:21

QT 調(diào)試

2011-06-22 16:08:40

Qt 多線程 事件循環(huán)

2011-06-13 10:03:19

Qt 多線程 編程

2011-06-22 16:02:37

Qt 多線程 重入

2011-06-16 10:38:13

Qt多線程編程

2011-06-20 13:43:08

Qt Socket 線程

2011-06-17 14:41:56

Qt

2011-06-30 17:51:17

QT 元類型 線程

2011-06-22 16:18:23

QT 多線程 QSocket

2011-06-24 15:30:22

QT 皮膚 QSS

2011-06-22 15:50:45

QT 線程

2011-06-22 15:09:34

Qt 線程 sleep

2011-06-10 12:44:09

2011-06-13 16:51:19

Qt Socket

2011-06-08 15:06:09

Qt 教程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)