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

詳解 Qt 線程間共享數(shù)據(jù)

移動(dòng)開(kāi)發(fā)
使用共享內(nèi)存。即使用一個(gè)兩個(gè)線程都能夠共享的變量(如全局變量),這樣兩個(gè)線程都能夠訪問(wèn)和修改該變量,從而達(dá)到共享數(shù)據(jù)的目的。

Qt 線程共享數(shù)據(jù)是本文介紹的內(nèi)容,多的不說(shuō),先來(lái)啃內(nèi)容。Qt線程共享數(shù)據(jù)主要有兩種方式:

使用共享內(nèi)存。即使用一個(gè)兩個(gè)線程都能夠共享的變量(如全局變量),這樣兩個(gè)線程都能夠訪問(wèn)和修改該變量,從而達(dá)到共享數(shù)據(jù)的目的;

使用singal/slot機(jī)制,把數(shù)據(jù)從一個(gè)線程傳遞到另外一個(gè)線程

***種辦法在各個(gè)編程語(yǔ)言都使用普遍,而第二種方式倒是QT的特有方式,下面主要學(xué)習(xí)一下這種方式:

在線程之間傳遞signal與在一個(gè)線程內(nèi)傳遞signal是不一樣的。在一個(gè)線程內(nèi)傳遞signal時(shí),emit語(yǔ)句會(huì)直接調(diào)用所有連接的slot并等待到所有slot被處理完;在線程之間傳遞signal時(shí),slot會(huì)被放到隊(duì)列中(queue),而emit這個(gè)signal后會(huì)馬上返回;默認(rèn)情況,線程之間使用queue機(jī)制,而線程內(nèi)使用direct機(jī)制,但在connect中可以改變這些默認(rèn)的機(jī)制。

  1. view plaincopy to clipboardprint?  
  2. //TextDevice.h    
  3. #ifndef TEXTDEVICE_H    
  4. #define TEXTDEVICE_H    
  5. #include <QThread>    
  6. #include <QString>    
  7. #include <QMutex>     
  8. class TextDevice : public QThread {     
  9.     Q_OBJECT     
  10. public:     
  11.     TextDevice();     
  12.     void run();     
  13.     void stop();     
  14. public slots:     
  15.     void write(const QString& text);     
  16. private:     
  17.     int m_count;     
  18.     QMutex m_mutex;     
  19. };    
  20. #endif // TEXTDEVICE_H     
  21.     
  22.     
  23. //TextDevice.cpp    
  24. #include <QMutexLocker>    
  25. #include <QDebug>    
  26. #include <QString>    
  27. #include "TextDevice.h"     
  28. TextDevice::TextDevice() {     
  29.     m_count = 0;     
  30. }     
  31. void TextDevice::run() {     
  32.     exec();     
  33. }     
  34. void TextDevice::stop() {     
  35.     quit();     
  36. }     
  37. void TextDevice::write(const QString& text) {     
  38.     QMutexLocker locker(&m_mutex);     
  39.     qDebug() << QString("Call %1: %2").arg(m_count++).arg(text);     
  40. }     
  41.     
  42. //TextThread.h    
  43. #ifndef TEXTTHREAD_H    
  44. #define TEXTTHREAD_H    
  45. #include <QThread>    
  46. #include <QString>     
  47. class TextThread : public QThread {     
  48.     Q_OBJECT     
  49. public:     
  50.     TextThread(const QString& text);     
  51.     void run();     
  52.     void stop();     
  53. signals:     
  54.     void writeText(const QString&);     
  55. private:     
  56.     QString m_text;     
  57.     bool m_stop;     
  58. };    
  59. #endif // TEXTTHREAD_H     
  60.     
  61. //TextThread.cpp    
  62. #include "TextThread.h"     
  63. TextThread::TextThread(const QString& text) : QThread() {     
  64.     m_text = text;     
  65.     m_stop = false;     
  66. }     
  67. void TextThread::stop() {     
  68.     m_stop = true;     
  69. }     
  70. void TextThread::run() {     
  71.     while(!m_stop) {     
  72.         emit writeText(m_text);     
  73.         sleep(1);     
  74.     }     
  75. }     
  76.     
  77. //main.cpp    
  78. #include <QApplication>    
  79. #include <QMessageBox>    
  80. #include "TextDevice.h"    
  81. #include "TextThread.h"     
  82.     
  83. int main(int argc, char** argv) {     
  84.     QApplication app(argc, argv);     
  85.     //啟動(dòng)線程     
  86.     TextDevice device;     
  87.     TextThread foo("foo"), bar("bar");     
  88.     //把兩個(gè)線程使用signal/slot連接起來(lái)     
  89.     QObject::connect(&foo, SIGNAL(writeText(const QString&)), &device, SLOT(write(const QString&)));     
  90.     QObject::connect(&bar, SIGNAL(writeText(const QString&)), &device, SLOT(write(const QString&)));     
  91.     //啟動(dòng)線程     
  92.     foo.start();     
  93.     bar.start();     
  94.     device.start();     
  95.     QMessageBox::information(0, "Threading", "Close me to stop.");     
  96.     //停止線程     
  97.     foo.stop();     
  98.     bar.stop();     
  99.     device.stop();     
  100.     //等待線程結(jié)束     
  101.     device.wait();     
  102.     foo.wait();     
  103.     bar.wait();     
  104.     return 0;     
  105. }    
  106. //TextDevice.h  
  107. #ifndef TEXTDEVICE_H  
  108. #define TEXTDEVICE_H  
  109. #include <QThread> 
  110. #include <QString> 
  111. #include <QMutex> 
  112. class TextDevice : public QThread {  
  113.     Q_OBJECT  
  114. public:  
  115.     TextDevice();  
  116.     void run();  
  117.     void stop();  
  118. public slots:  
  119.     void write(const QString& text);  
  120. private:  
  121.     int m_count;  
  122.     QMutex m_mutex;  
  123. };  
  124. #endif // TEXTDEVICE_H  
  125.  
  126.  
  127. //TextDevice.cpp  
  128. #include <QMutexLocker> 
  129. #include <QDebug> 
  130. #include <QString> 
  131. #include "TextDevice.h"  
  132. TextDevice::TextDevice() {  
  133.     m_count = 0;  
  134. }  
  135. void TextDevice::run() {  
  136.     exec();  
  137. }  
  138. void TextDevice::stop() {  
  139.     quit();  
  140. }  
  141. void TextDevice::write(const QString& text) {  
  142.     QMutexLocker locker(&m_mutex);  
  143.     qDebug() << QString("Call %1: %2").arg(m_count++).arg(text);  
  144. }  
  145.  
  146. //TextThread.h  
  147. #ifndef TEXTTHREAD_H  
  148. #define TEXTTHREAD_H  
  149. #include <QThread> 
  150. #include <QString> 
  151. class TextThread : public QThread {  
  152.     Q_OBJECT  
  153. public:  
  154.     TextThread(const QString& text);  
  155.     void run();  
  156.     void stop();  
  157. signals:  
  158.     void writeText(const QString&);  
  159. private:  
  160.     QString m_text;  
  161.     bool m_stop;  
  162. };  
  163. #endif // TEXTTHREAD_H  
  164.  
  165. //TextThread.cpp  
  166. #include "TextThread.h"  
  167. TextThread::TextThread(const QString& text) : QThread() {  
  168.     m_text = text;  
  169.     m_stop = false;  
  170. }  
  171. void TextThread::stop() {  
  172.     m_stop = true;  
  173. }  
  174. void TextThread::run() {  
  175.     while(!m_stop) {  
  176.         emit writeText(m_text);  
  177.         sleep(1);  
  178.     }  
  179. }  
  180.  
  181. //main.cpp  
  182. #include <QApplication> 
  183. #include <QMessageBox> 
  184. #include "TextDevice.h"  
  185. #include "TextThread.h"  
  186. int main(int argc, char** argv) {  
  187.     QApplication app(argc, argv);  
  188.     //啟動(dòng)線程  
  189.     TextDevice device;  
  190.     TextThread foo("foo"), bar("bar");  
  191.     //把兩個(gè)線程使用signal/slot連接起來(lái)  
  192.     QObject::connect(&foo, SIGNAL(writeText(const QString&)), &device, SLOT(write(const QString&)));  
  193.     QObject::connect(&bar, SIGNAL(writeText(const QString&)), &device, SLOT(write(const QString&)));  
  194.     //啟動(dòng)線程  
  195.     foo.start();  
  196.     bar.start();  
  197.     device.start();  
  198.     QMessageBox::information(0, "Threading", "Close me to stop.");  
  199.     //停止線程  
  200.     foo.stop();  
  201.     bar.stop();  
  202.     device.stop();  
  203.     //等待線程結(jié)束  
  204.     device.wait();  
  205.     foo.wait();  
  206.     bar.wait();  
  207.     return 0;  

#p#

上面例子代碼可以看出兩個(gè)線程之間傳送了類型為QString的信息。像QString等這些QT本身定義的類型,直接傳送即可。但如果是自己定義的類型如果想使用signal/slot來(lái)傳遞的話,則沒(méi)有這么簡(jiǎn)單。直接使用的話,會(huì)產(chǎn)生下面這種錯(cuò)誤:

  1. QObject::connect: Cannot queue arguments of type 'TextAndNumber' (Make sure 'TextAndNumber' is registed using qRegisterMetaType().) 

原因:當(dāng)一個(gè)signal被放到隊(duì)列中(queued)時(shí),它的參數(shù)(arguments)也會(huì)被一起一起放到隊(duì)列中(queued起來(lái)),這就意味著參數(shù)在被傳送到slot之前需要被拷貝、存儲(chǔ)在隊(duì)列中(queue)中;為了能夠在隊(duì)列中存儲(chǔ)這些參數(shù)(argument),Qt需要去construct、destruct、copy這些對(duì)象,而為了讓Qt知道怎樣去作這些事情,參數(shù)的類型需要使用qRegisterMetaType來(lái)注冊(cè)(如錯(cuò)誤提示中的說(shuō)明)

步驟:(以自定義TextAndNumber類型為例)

自定一種類型,在這個(gè)類型的頂部包含:#include <QMetaType>

在類型定義完成后,加入聲明:Q_DECLARE_METATYPE(TextAndNumber);

在main()函數(shù)中注冊(cè)這種類型:qRegisterMetaType<TextAndNumber>("TextAndNumber");

如果還希望使用這種類型的引用,可同樣要注冊(cè):qRegisterMetaType<TextAndNumber>("TextAndNumber&");

  1. view plaincopy to clipboardprint?  
  2. //TextAndNumber.h     
  3. #ifndef TEXTANDNUMBER_H     
  4. #define TEXTANDNUMBER_H     
  5. #include <QMetaType>     
  6. //必須包含QMetaType,否則會(huì)出現(xiàn)下面錯(cuò)誤:     
  7. //error: expected constructor, destructor, or type conversion before ‘;’ token     
  8. #include <QString>     
  9. class TextAndNumber {     
  10. public:     
  11.     TextAndNumber();     
  12.     TextAndNumber(int, QString);     
  13.     int count();     
  14.     QString text();     
  15. private:     
  16.     int m_count;     
  17.     QString m_text;     
  18. };     
  19. Q_DECLARE_METATYPE(TextAndNumber);     
  20. #endif // TEXTANDNUMBER_H     
  21.     
  22. //TextAndNumber.cpp     
  23. #include "TextAndNumber.h"     
  24. TextAndNumber::TextAndNumber() {     
  25. }     
  26. TextAndNumber::TextAndNumber(int count, QString text) {     
  27.     m_count = count;     
  28.     m_text = text;     
  29. }     
  30. int TextAndNumber::count() {     
  31.     return m_count;     
  32. }     
  33. QString TextAndNumber::text() {     
  34.     return m_text;     
  35. }     
  36.     
  37. //TextDevice.h     
  38. #ifndef TEXTDEVICE_H     
  39. #define TEXTDEVICE_H     
  40. #include <QThread>     
  41. #include <QDebug>     
  42. #include <QString>     
  43. #include "TextAndNumber.h"     
  44. class TextDevice : public QThread {     
  45.     Q_OBJECT     
  46. public:     
  47.     TextDevice();     
  48.     void run();     
  49.     void stop();     
  50. public slots:     
  51.     void write(TextAndNumber& tran);     
  52. private:     
  53.     int m_count;     
  54. };     
  55. #endif // TEXTDEVICE_H     
  56.     
  57. //TextDevice.cpp     
  58. #include "TextDevice.h"     
  59. TextDevice::TextDevice() : QThread() {     
  60.     m_count = 0;     
  61. }     
  62. void TextDevice::run() {     
  63.     exec();     
  64. }     
  65. void TextDevice::stop() {     
  66.     quit();     
  67. }     
  68. void TextDevice::write(TextAndNumber& tran) {     
  69.     qDebug() << QString("Call %1 (%3): %2").arg(m_count++).arg(tran.text()).arg(tran.count());     
  70. }     
  71.     
  72. //TextThread.h     
  73. #ifndef TEXTTHREAD_H     
  74. #define TEXTTHREAD_H     
  75. #include <QThread>     
  76. #include <QString>     
  77. #include "TextAndNumber.h"     
  78. class TextThread : public QThread {     
  79.     Q_OBJECT     
  80. public:     
  81.     TextThread(const QString& text);     
  82.     void run();     
  83.     void stop();     
  84. signals:     
  85.     void writeText(TextAndNumber& tran);     
  86. private:     
  87.     QString m_text;     
  88.     int m_count;     
  89.     bool m_stop;     
  90. };     
  91.     
  92. #endif // TEXTTHREAD_H     
  93.     
  94. //TextThread.cpp     
  95. #include "TextThread.h"     
  96. TextThread::TextThread(const QString& text) : QThread() {     
  97.     m_text = text;     
  98.     m_stop = false;     
  99.     m_count = 0;     
  100. }     
  101. void TextThread::run() {     
  102.     while(!m_stop) {     
  103.         TextAndNumber tn(m_count++, m_text);     
  104.         emit writeText(tn);     
  105.         sleep(1);     
  106.     }     
  107. }     
  108. void TextThread::stop() {     
  109.     m_stop = true;     
  110. }     
  111.     
  112. //main.cpp     
  113. #include <QApplication>     
  114. #include <QMessageBox>     
  115. #include "TextThread.h"     
  116. #include "TextDevice.h"     
  117. #include "TextAndNumber.h"     
  118. int main(int argc, char *argv[])     
  119. {     
  120.     QApplication app(argc, argv);     
  121.     qRegisterMetaType<TextAndNumber>("TextAndNumber");     
  122.     qRegisterMetaType<TextAndNumber>("TextAndNumber&");     
  123.     TextDevice device;     
  124.     TextThread foo("foo"), bar("bar");     
  125.     QObject::connect(&foo, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&)));     
  126.     QObject::connect(&bar, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&)));     
  127.     device.start();     
  128.     foo.start();     
  129.     bar.start();     
  130.     QMessageBox::information(0, "Threading", "Click me to close");     
  131.     foo.stop();     
  132.     bar.stop();     
  133.     device.stop();     
  134.     foo.wait();     
  135.     bar.wait();     
  136.     device.wait();     
  137.     qDebug() << "Application end.";     
  138.     return 0;     
  139. }   

小結(jié):詳解 Qt 線程共享數(shù)據(jù)的內(nèi)容介紹完了,希望本文對(duì)你有所幫助!

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

2020-12-14 08:43:56

線程進(jìn)程資源

2011-07-01 13:03:32

QT 線程 串口

2023-10-26 08:16:20

C++線程

2025-01-07 12:58:28

2011-06-30 18:03:58

QT 多線程 服務(wù)器

2011-06-23 18:37:02

Qt 數(shù)據(jù)庫(kù)

2011-06-22 17:09:50

QT 進(jìn)程 通信

2011-08-30 14:25:06

QT數(shù)據(jù)庫(kù)

2010-03-16 15:32:26

2017-02-16 08:13:17

2011-06-22 10:12:08

Qt 線程

2020-08-10 08:28:19

ZeroMQCPython

2011-07-05 09:54:04

2011-07-01 14:06:57

Qt sqlite

2018-01-12 14:35:00

Linux進(jìn)程共享內(nèi)存

2011-06-20 17:33:58

Qt MeegoTouch Maemo

2011-06-28 15:01:01

Qt PIMPL

2011-06-24 10:05:51

QT 對(duì)象 父對(duì)象

2021-03-05 07:38:52

C++線程編程開(kāi)發(fā)技術(shù)

2011-06-30 17:51:17

QT 元類型 線程
點(diǎn)贊
收藏

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