做项目时遭遇用户界面冻结的问题,究其原因是槽函数里装了一个需要CPU密集操作的功能。使用多线程,可以解决界面冻结的问题。

多线程的几大特点:

1.多线程的执行顺序无法保证,与操作系统的调度策略和线程优先级等因素有关。

2.多线程的切换可能发生在任何时刻、任何地点。

3.多线程对代码的敏感度高,因此对代码的细微修改都可能产生意想不到的效果。

先由一个简单的例子引出多线程

先作出这个简单的界面

qt多线程写sqlite数据库_多线程

“开始”对应的槽函数是:slotStart()

“停止”对应的槽函数是:slotStop()

本例中的线程(workthread类)实现的功能是,从0到9循环打印,0至9各占一排。

则该线程的具体实现如下:

#ifndef WORKTHREAD_H
#define WORKTHREAD_H

#include <QThread>
class WorkThread : public QThread
{
    Q_OBJECT
public:
    WorkThread();
protected:
    void run();
};

#endif // WORKTHREAD_H
#include "workthread.h"
#include <QtDebug>
WorkThread::WorkThread()
{

}
void WorkThread::run()
{
    while(true)
    {
        for(int n=0;n<10;n++)
            qDebug()<<n<<n<<n<<n<<n<<n<<n<<n;
    }
}

好了,现在该在本窗口对象的头文件里添加这个线程属性

private:
	WorkThread *workThread[MAXSIZE];

MAXSIZE表示最大生成的线程数,可以根据个人喜好自行选择,只要你的CPU带得动。当然,这里为了展示多线程的特性,我们分别将MAXSIZE置为1及5。

完善之前两个槽函数的功能。

void CH1201::slotStart()
{
	qDebug() << "slotStart";
	for (int i = 0; i < MAXSIZE; i++)
	{
		workThread[i] = new WorkThread();
	}
	for (int i = 0; i < MAXSIZE; i++)
	{
		workThread[i]->start();
	}
	ui.startBtn->setEnabled(false);
	ui.stopBtn->setEnabled(true);
}

void CH1201::slotStop()
{

	for (int i = 0; i < MAXSIZE; i++)
	{
		workThread[i]->terminate();
		workThread[i]->wait();
	}
	ui.startBtn->setEnabled(true);
	ui.stopBtn->setEnabled(false);
}

线程类方法顾名思义大致都能看懂。现在多说两句我自己没怎么接触的:

1.terminate(),依次终止保存在workThread[]数组中的WorkThread类实例。但是terminate()函数并不会立刻终止这个线程,该线程何时终止取决于操作系统的调度策略。

2.wait(),使得线程阻塞等待直到退出或超时。
下面观赏一下qDebug()的结果:

下图是MAXSIZE为5是的打印结果,可以看出输出结果是乱序的,我们根本无法猜测操作系统到底是怎么调度这五个线程的。

qt多线程写sqlite数据库_vs_02

下图是MAXSIZE为1的打印结果,输出数字顺序有规律,显然只有一个线程在工作。

qt多线程写sqlite数据库_vs_03

PS:作为小白,IDE用的VS2015,我刚开始不知道qDebug打印的调试信息显示在哪里,查了一会儿才知道,qDebug打印的调试信息显示在console。至于调出console的方法也很简单,点击VS左上菜单之一“项目”,选择最下方的“属性”,点击“链接器”,点击“链接器”树下的“系统”,目光移到弹出窗口的中央,更改”子系统“为:”控制台/SUBSYSTEM:CONSOLE“。