Qt 学习之路 :线程简介
Qt 使用QThread
来管理线程。下面来看一个简单的例子:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
///!!! Qt5
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *widget = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout;
widget->setLayout(layout);
QLCDNumber *lcdNumber = new QLCDNumber(this);
layout->addWidget(lcdNumber);
QPushButton *button = new QPushButton(tr("Start"), this);
layout->addWidget(button);
setCentralWidget(widget);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, [=]() {
static int sec = 0;
lcdNumber->display(QString::number(sec++));
});
WorkerThread *thread = new WorkerThread(this);
connect(button, &QPushButton::clicked, [=]() {
timer->start(1);
for (int i = 0; i < 2000000000; i++);
timer->stop();
});
}
|
我们的主界面有一个用于显示时间的 LCD 数字面板还有一个用于启动任务的按钮。程序的目的是用户点击按钮,开始一个非常耗时的运算(程序中我们以一个 2000000000 次的循环来替代这个非常耗时的工作,在真实的程序中,这可能是一个网络访问,可能是需要复制一个很大的文件或者其它任务),同时 LCD 开始显示逝去的毫秒数。毫秒数通过一个计时器QTimer
进行更新。计算完成后,计时器停止。这是一个很简单的应用,也看不出有任何问题。但是当我们开始运行程序时,问题就来了:点击按钮之后,程序界面直接停止响应,直到循环结束才开始重新更新。
有经验的开发者立即指出,这里需要使用线程。这是因为 Qt 中所有界面都是在 UI 线程中(也被称为主线程,就是执行了QApplication::exec()
的线程),在这个线程中执行耗时的操作(比如那个循环),就会阻塞 UI 线程,从而让界面停止响应。界面停止响应,用户体验自然不好,不过更严重的是,有些窗口管理程序会检测到你的程序已经失去响应,可能会建议用户强制停止程序,这样一来你的程序可能就此终止,任务再也无法完成。所以,为了避免这一问题,我们要使用 QThread 开启一个新的线程:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
///!!! Qt5
class WorkerThread : public QThread
{
Q_OBJECT
public:
WorkerThread(QObject *parent = 0)
: QThread(parent)
{
}
protected:
void run()
{
for (int i = 0; i < 1000000000; i++);
emit done();
}
signals:
void done();
};
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *widget = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout;
widget->setLayout(layout);
lcdNumber = new QLCDNumber(this);
layout->addWidget(lcdNumber);
QPushButton *button = new QPushButton(tr("Start"), this);
layout->addWidget(button);
setCentralWidget(widget);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, [=]() {
static int sec = 0;
lcdNumber->display(QString::number(sec++));
});
WorkerThread *thread = new WorkerThread(this);
connect(thread, &WorkerThread::done, timer, &QTimer::stop);
connect(thread, &WorkerThread::finished, thread, &WorkerThread::deleteLater);
connect(button, &QPushButton::clicked, [=]() {
timer->start(1);
thread->start();
});
}
|
注意,我们增加了一个WorkerThread
类。WorkerThread
继承自QThread
类,重写了其run()
函数。我们可以认为,run()
函数就是新的线程需要执行的代码。在这里就是要执行这个循环,然后发出计算完成的信号。而在按钮点击的槽函数中,使用QThread::start()
函数启动一个线程(注意,这里不是run()
函数)。再次运行程序,你会发现现在界面已经不会被阻塞了。另外,我们将WorkerThread::deleteLater()
函数与WorkerThread::finished()
信号连接起来,当线程完成时,系统可以帮我们清除线程实例。这里的finished()
信号是系统发出的,与我们自定义的done()
信号无关。
这是 Qt 线程的最基本的使用方式之一(确切的说,这种使用已经不大推荐使用,不过因为看起来很清晰,而且简单使用起来也没有什么问题,所以还是有必要介绍)。代码看起来很简单,不过,如果你认为 Qt 的多线程编程也很简单,那就大错特错了。Qt 多线程的优势设计使得它使用起来变得容易,但是坑很多,稍不留神就会被绊住,尤其是涉及到与 QObject 交互的情况。稍懂多线程开发的童鞋都会知道,调试多线程开发简直就是煎熬。下面几章,我们会更详细介绍有关多线程编程的相关内容。
Qt 学习之路 :线程简介的更多相关文章
- Qt 学习之路 2(71):线程简介
Qt 学习之路 2(71):线程简介 豆子 2013年11月18日 Qt 学习之路 2 30条评论 前面我们讨论了有关进程以及进程间通讯的相关问题,现在我们开始讨论线程.事实上,现代的程序中,使用线程 ...
- Qt 学习之路 2(13):对话框简介
Qt 学习之路 2(13):对话框简介 豆子 2012年9月14日 Qt 学习之路 2 53条评论 对话框是 GUI 程序中不可或缺的组成部分.很多不能或者不适合放入主窗口的功能组件都必须放在 ...
- Qt 学习之路 2(6):Qt 模块简介
Home / Qt 学习之路 2 / Qt 学习之路 2(6):Qt 模块简介 豆子 2012年8月26日 Qt 学习之路 2 20条评论 Qt 5 与 Qt 4 最大的一个区别之一是底层架构 ...
- Qt 学习之路 2(74):线程和 QObject
Home / Qt 学习之路 2 / Qt 学习之路 2(74):线程和 QObject Qt 学习之路 2(74):线程和 QObject 豆子 2013年12月3日 Qt 学习之路 2 2 ...
- Qt 学习之路 2(73):Qt 线程相关类
Home / Qt 学习之路 2 / Qt 学习之路 2(73):Qt 线程相关类 Qt 学习之路 2(73):Qt 线程相关类 豆子 2013年11月26日 Qt 学习之路 2 7条评论 希 ...
- Qt 学习之路 2(72):线程和事件循环
Qt 学习之路 2(72):线程和事件循环 <理解不清晰,不透彻> -- 有需求的话还需要进行专题学习 豆子 2013年11月24日 Qt 学习之路 2 34条评论 前面一章我 ...
- Qt 学习之路 2(24):Qt 绘制系统简介
Qt 学习之路 2(24):Qt 绘制系统简介 豆子 2012年10月30日 Qt 学习之路 2 77条评论 Qt 的绘图系统允许使用相同的 API 在屏幕和其它打印设备上进行绘制.整个绘图系统基于Q ...
- Qt 学习之路 2(7):MainWindow 简介
Qt 学习之路 2(7):MainWindow 简介 豆子 2012年8月29日 Qt 学习之路 2 29条评论 前面一篇大致介绍了 Qt 各个模块的相关内容,目的是对 Qt 框架有一个高屋建 ...
- Qt 学习之路 2(2):Qt 简介
Home / Qt 学习之路 2 / Qt 学习之路 2(2):Qt 简介 Qt 学习之路 2(2):Qt 简介 豆子 2012年8月21日 Qt 学习之路 2 43条评论 Qt 是一个著名的 ...
- 《Qt 学习之路 2》目录
<Qt 学习之路 2>目录 <Qt 学习之路 2>目录 豆子 2012年8月23日 Qt 学习之路 2 177条评论 <Qt 学习之路 2>目录 序 Qt ...
随机推荐
- HTML5有语义的内联元素详解
HTML5有语义的内联元素详解 time标签 time 元素表示一个时间值,比如 5:35 P.M., EST, April 23, 2007.例如: Example Source Code:< ...
- cloudera-scm-server ip改了怎么办了
1.vi /etc/cloudera-scm-agent/config.ini #改下ip 2.manager 老只看到一个主机 rm -f /var/lib/cloudera-scm-agent/u ...
- ipython与python的区别
http://mba.shengwushibie.com/itbook/BookChapter.asp?id=8745 http://www.cnblogs.com/yangze/archive/20 ...
- windows server 2008 asp连接数据库sql2000失败
由于服务器现在的服务器已不能承受了,需要替换服务器并把window2003升级为window2008,把所有数据都平移过来.平移完后遇到ASP总是不能连接上sql2000,这让我非常郁闷,处理了好几个 ...
- C#执行oracle返回游标类型的存储过程
存储过程代码为: create or replace procedure proc_test(pCursor OUT pak_pub.ut_cursor) AS begin -- 使用游标 open ...
- 老oj曼哈顿最小生成树
Description 平面坐标系xOy内,给定n个顶点V = (x , y).对于顶点u.v,u与v之间的距离d定义为|xu – xv| + |yu – yv| 你的任务就是求出这n个顶点的最小生成 ...
- 优化MYSQL FILESORT
用Explain分析SQL语句的时候,经常发现有的语句在Extra列会出现Using filesort,根据mysql官方文档对他的描述: 引用 MySQL must do an extra pass ...
- IIS 启用或关闭目录浏览
如果不希望启用目录浏览,请确保配置了默认文档并且该文件存在. 使用 IIS 管理器启用目录浏览. 打开 IIS 管理器. 在“功能”视图中,双击“目录浏览”. 在“目录浏览”页上,在“操作”窗格中单击 ...
- HDU 1203 I NEED A OFFER! 01背包
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1203 解题思路:简单的01背包,用dp[i]表示花费不超过i时的最大可能性 状态转移方程 dp[i]= ...
- hdu 4322 最大费用流
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4322 #include <cstdio> #include <cstring> ...