QT线程共享数据(转载)

Qt线程间共享数据主要有两种方式:
 •使用共享内存。即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的;
 •使用singal/slot机制,把数据从一个线程传递到另外一个线程。
 第一种办法在各个编程语言都使用普遍,而第二种方式倒是QT的特有方式,下面主要学习一下这种方式:
 在线程之间传递signal与在一个线程内传递signal是不一样的。在一个线程内传递signal时,emit语句会直接调用所有连接的slot并等待到所有slot被处理完;在线程之间传递signal时,slot会被放到队列中(queue),而emit这个signal后会马上返回;默认情况,线程之间使用queue机制,而线程内使用direct机制,但在connect中可以改变这些默认的机制。
 view plaincopy to clipboardprint?01.//TextDevice.h#ifndef TEXTDEVICE_H#define TEXTDEVICE_H#include <QThread>#include <QString>#include <QMutex>class TextDevice : public QThread {
02. Q_OBJECT
03.public:
04. TextDevice();
05. void run();
06. void stop();
07.public slots:
08. void write(const QString& text);
09.private:
10. int m_count;
11. QMutex m_mutex;
12.};
13.#endif // TEXTDEVICE_H//TextDevice.cpp#include <QMutexLocker>#include <QDebug>#include <QString>#include "TextDevice.h"TextDevice::TextDevice() {
14. m_count = 0;
15.}
16.void TextDevice::run() {
17. exec();
18.}
19.void TextDevice::stop() {
20. quit();
21.}
22.void TextDevice::write(const QString& text) {
23. QMutexLocker locker(&m_mutex);
24. qDebug() << QString("Call %1: %2").arg(m_count++).arg(text);
25.}
26.
27.//TextThread.h#ifndef TEXTTHREAD_H#define TEXTTHREAD_H#include <QThread>#include <QString>class TextThread : public QThread {
28. Q_OBJECT
29.public:
30. TextThread(const QString& text);
31. void run();
32. void stop();
33.signals:
34. void writeText(const QString&);
35.private:
36. QString m_text;
37. bool m_stop;
38.};
39.#endif // TEXTTHREAD_H//TextThread.cpp#include "TextThread.h"TextThread::TextThread(const QString& text) : QThread() {
40. m_text = text;
41. m_stop = false;
42.}
43.void TextThread::stop() {
44. m_stop = true;
45.}
46.void TextThread::run() {
47. while(!m_stop) {
48. emit writeText(m_text);
49. sleep(1);
50. }
51.}
52.
53.//main.cpp#include <QApplication>#include <QMessageBox>#include "TextDevice.h"#include "TextThread.h"int main(int argc, char** argv) {
54. QApplication app(argc, argv);
55. //启动线程 TextDevice device;
56. TextThread foo("foo"), bar("bar");
57. //把两个线程使用signal/slot连接起来 QObject::connect(&foo, SIGNAL(writeText(const QString&)), &device, SLOT(write(const QString&)));
58. QObject::connect(&bar, SIGNAL(writeText(const QString&)), &device, SLOT(write(const QString&)));
59. //启动线程 foo.start();
60. bar.start();
61. device.start();
62. QMessageBox::information(0, "Threading", "Close me to stop.");
63. //停止线程 foo.stop();
64. bar.stop();
65. device.stop();
66. //等待线程结束 device.wait();
67. foo.wait();
68. bar.wait();
69. return 0;
70.}
71.

上面例子代码可以看出两个线程之间传送了类型为QString的信息。像QString等这些QT本身定义的类型,直接传送即可。但如果是自己定义的类型如果想使用signal/slot来传递的话,则没有这么简单。直接使用的话,会产生下面这种错误:
 QObject::connect: Cannot queue arguments of type 'TextAndNumber' (Make sure 'TextAndNumber' is registed using qRegisterMetaType().)
 原因:当一个signal被放到队列中(queued)时,它的参数(arguments)也会被一起一起放到队列中(queued起来),这就意味着参数在被传送到slot之前需要被拷贝、存储在队列中(queue)中;为了能够在队列中存储这些参数(argument),Qt需要去construct、destruct、copy这些对象,而为了让Qt知道怎样去作这些事情,参数的类型需要使用qRegisterMetaType来注册(如错误提示中的说明)
 步骤:(以自定义TextAndNumber类型为例)
 •自定一种类型,在这个类型的顶部包含:#include <QMetaType>
 •在类型定义完成后,加入声明:Q_DECLARE_METATYPE(TextAndNumber);
 •在main()函数中注册这种类型:qRegisterMetaType<TextAndNumber>("TextAndNumber");
 •如果还希望使用这种类型的引用,可同样要注册:qRegisterMetaType<TextAndNumber>("TextAndNumber&");
 view plaincopy to clipboardprint?01.//TextAndNumber.h#ifndef TEXTANDNUMBER_H#define TEXTANDNUMBER_H#include <QMetaType>//必须包含QMetaType,否则会出现下面错误://error: expected constructor, destructor, or type conversion before ‘;’ token#include <QString>class TextAndNumber {
02.public:
03. TextAndNumber();
04. TextAndNumber(int, QString);
05. int count();
06. QString text();
07.private:
08. int m_count;
09. QString m_text;
10.};
11.Q_DECLARE_METATYPE(TextAndNumber);
12.#endif // TEXTANDNUMBER_H//TextAndNumber.cpp#include "TextAndNumber.h"TextAndNumber::TextAndNumber() {
13.}
14.TextAndNumber::TextAndNumber(int count, QString text) {
15. m_count = count;
16. m_text = text;
17.}
18.int TextAndNumber::count() {
19. return m_count;
20.}
21.QString TextAndNumber::text() {
22. return m_text;
23.}
24.
25.//TextDevice.h#ifndef TEXTDEVICE_H#define TEXTDEVICE_H#include <QThread>#include <QDebug>#include <QString>#include "TextAndNumber.h"class TextDevice : public QThread {
26. Q_OBJECT
27.public:
28. TextDevice();
29. void run();
30. void stop();
31.public slots:
32. void write(TextAndNumber& tran);
33.private:
34. int m_count;
35.};
36.
37.#endif // TEXTDEVICE_H//TextDevice.cpp#include "TextDevice.h"TextDevice::TextDevice() : QThread() {
38. m_count = 0;
39.}
40.void TextDevice::run() {
41. exec();
42.}
43.void TextDevice::stop() {
44. quit();
45.}
46.void TextDevice::write(TextAndNumber& tran) {
47. qDebug() << QString("Call %1 (%3): %2").arg(m_count++).arg(tran.text()).arg(tran.count());
48.}
49.
50.//TextThread.h#ifndef TEXTTHREAD_H#define TEXTTHREAD_H#include <QThread>#include <QString>#include "TextAndNumber.h"class TextThread : public QThread {
51. Q_OBJECT
52.public:
53. TextThread(const QString& text);
54. void run();
55. void stop();
56.signals:
57. void writeText(TextAndNumber& tran);
58.private:
59. QString m_text;
60. int m_count;
61. bool m_stop;
62.};
63.
64.#endif // TEXTTHREAD_H//TextThread.cpp#include "TextThread.h"TextThread::TextThread(const QString& text) : QThread() {
65. m_text = text;
66. m_stop = false;
67. m_count = 0;
68.}
69.void TextThread::run() {
70. while(!m_stop) {
71. TextAndNumber tn(m_count++, m_text);
72. emit writeText(tn);
73. sleep(1);
74. }
75.}
76.void TextThread::stop() {
77. m_stop = true;
78.}
79.
80.//main.cpp#include <QApplication>#include <QMessageBox>#include "TextThread.h"#include "TextDevice.h"#include "TextAndNumber.h"int main(int argc, char *argv[])
81.{
82. QApplication app(argc, argv);
83. qRegisterMetaType<TextAndNumber>("TextAndNumber");
84. qRegisterMetaType<TextAndNumber>("TextAndNumber&");
85. TextDevice device;
86. TextThread foo("foo"), bar("bar");
87. QObject::connect(&foo, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&)));
88. QObject::connect(&bar, SIGNAL(writeText(TextAndNumber&)), &device, SLOT(write(TextAndNumber&)));
89. device.start();
90. foo.start();
91. bar.start();
92. QMessageBox::information(0, "Threading", "Click me to close");
93.
94. foo.stop();
95. bar.stop();
96. device.stop();
97. foo.wait();
98. bar.wait();
99. device.wait();
100. qDebug() << "Application end.";
101. return 0;
102.}

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/swingline/archive/2010/05/30/5635288.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值