首页 > 代码库 > 【Qt学习笔记】8.Qt中的多线程

【Qt学习笔记】8.Qt中的多线程

一、界面线程与工作线程


GUI程序的主线程:

GUI的用户输入主要来自鼠标、键盘,称为事件。

处理事件的主循环,称为 事件循环。 这个用于处理各种界面的线程,称为 界面线程


GUI界面卡死

所有的事件处理函数(slots)都应该迅速返回,否则主界面会卡死

例如:鼠标点击一个按钮后,这个处理函数要尽快的返回。在它处理期间,界面是卡死的。(因为此函数处于事件循环中)

解决:把长时间的任务放到另一个线程(工作线程)中来完成,保持界面处于活动的状态。


二、定时器(Timer)

定时器用于实现定时操作,如:

每3秒钟自动保存一次

每500毫秒闪烁一次

每1秒刷新显示一次界面


使用方法:

1:重写virtual void timerEvent( QTimerEvent* event );


2:启动定时器,指定时间间隔(毫秒)

m_timerld = startTimer(500);



小练习:

实现一个文字时钟,显示系统当前时间

class Test8_1a_12_8 : public QMainWindow
{
    Q_OBJECT

public:
    Test8_1a_12_8(QWidget *parent = Q_NULLPTR);
	virtual void timerEvent(QTimerEvent* event);		//重写该函数(继承自QObject)

private:
    Ui::Test8_1a_12_8Class ui;
	int m_timerId;	//每个Timer有一个id
};

Test8_1a_12_8::Test8_1a_12_8(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	m_timerId = startTimer(500);
}

void Test8_1a_12_8::timerEvent(QTimerEvent* event)
{
	//可以有多个定时器,每个定时器有不同的处理
	if ( event->timerId() == m_timerId )
	{
		QTime now = QTime::currentTime();
		QString text = now.toString("HH:mm:ss");
		ui.lineEditTime->setText(text);
	}
}

效果:

技术分享


关于定时器,要注意以下:

1、定时器并不是线程:定时器时间和普通鼠标、键盘事件一样,进入事件循环进行处理,因此,定时器的处理函数需要尽快完成,不然也会把界面卡死;

2、定时器不是精确的,因为它需要放在事件循环中处理,因此如果其他事件占用了较多的事件,会导致定时器不够精确



三、创建线程

在Qt里,线程相关的类:

QThread:线程

QMutex:互斥锁

QSemaphore:信号量


创建线程的方法:

1、派生一个线程类,继承自QThread,然后重写入口函数run()方法

启动:start()

回收:wait()


2、添加一些成员函数,用于查询任务的状态和进度

状态: int GetStatus(); 返回值: 1(已完成) 2(正在进行) 3(发生错误,已终止)

进度:int GetProgress();    返回值:  0 ~ 100



创建工作线程:

工作线程就是一个普通的线程,区别于“界面线程”


当一个事件处理可能需要较长的时间,就创建一个线程来完成它,以免线程卡死。

步骤:

1、创建,并启动一个工作线程

2、显示一个进度条或等待对话框

3、启动一个定时器,定时查询工作线程的进度和状态,在其完成之后,填满进度条,结束等待


小练习:

模拟传送一个文件,显示任务进度

技术分享

技术分享

技术分享


代码:

github:

https://github.com/HonestFox/Qt/tree/master/12_8FileTransferStatu


【Qt学习笔记】8.Qt中的多线程