Qt中使用多线程的方法

1.Qt中使用多线程的注意事项

  • Qt默认是单线程的,MainWindow的那个线程就是主线程,也被称为UI线程

  • 子线程只负责业务逻辑、数据的处理,不能越级对主线程(UI线程)中显示的UI界面进行操作

  • 主线程如果要和子线程进行数据交互,要使用信号槽

2.QThread类

QThread类继承自QObject,可以把它看成一个QObject,只不过多了个把某个成员函数放到子线程内运行的能力,而且既然他是QObject的子类,他也可以使用信号槽那些东西。

2.1run()方法

QThread类本身不是线程,实际上它只有调用start()后才会创建一个新的线程,然后把run()函数丢到这个新的线程中运行。==正常情况下,只有QThread类的run()函数才会在子线程中运行,其他的比如槽函数,都不在子线程中==

  • 这个是多线程的核心,它是Qt在创建的子线程中所执行的任务

  • 这个函数是个虚函数,也就是说我们得创建QThread的子类并重新这个方法才行

  • 这个函数的属性是Protected,我们只能调用start()方法来开启子线程对run()函数的执行

2.2线程ID

写Qt多线程 + 槽函数时,在调试阶段一定要在子线程中输出线程ID试试,免得写了半天结果槽函数没在子线程中运行

法一:直接输出运行该行代码的线程的ID

1
2
3
4
5
void run()
{
...;
qDebug() << "Run Thread ID = " << QThread::currentThreadId();
}

法二:输出某变量所属线程的ID

1
2
test_thread *t1 = new test_thread();
qDebug() << "t1 Thread ID = " << t1->thread()->currentThreadId();

3.Qt使用子线程的方法

  • Qt中有2种多线程编程的方法,且各有优势

法一、继承QThread,并重写run()函数

这是最常见的使用多线程的方法,run()中的业务逻辑会被放到子线程中使用

该方法包括以下缺点:

  • 假设要在一个子线程中处理多个任务,所有的处理逻辑都需要写到run()函数中,这样该函数中的处理逻辑就会变得非常混乱,不太容易维护

法二、继承QObject

1.创建一个新的类,让这个类从QObject派生

1
2
3
4
class MyWork:public QObject
{
.......
}

2.在这个类中添加一个公共的成员函数,函数体就是我们要子线程中执行的业务逻辑

1
2
3
4
5
6
7
class MyWork:public QObject
{
public:
.......
// 函数名自己指定, 叫什么都可以, 参数可以根据实际需求添加
void working();
}

3.在主线程中创建一个QThread对象, 这就是子线程的对象
QThread* sub = new QThread;
4.在主线程中创建工作的类对象(千万不要指定给创建的对象指定父对象)

1
2
MyWork* work = new MyWork(this); // error
MyWork* work = new MyWork; // ok

5.将MyWork对象移动到创建的子线程对象中, 需要调用QObject类提供的moveToThread()方法

1
2
3
4
// void QObject::moveToThread(QThread *targetThread);
// 如果给work指定了父对象, 这个函数调用就失败了
// 提示: QObject::moveToThread: Cannot move objects with a parent
work->moveToThread(sub); // 移动到子线程中工作

6.启动子线程,调用 start(), 这时候线程启动了, 但是移动到线程中的对象并没有工作

7.调用MyWork类对象的工作函数,让这个函数开始执行,这时候是在移动到的那个子线程中运行的

1
2
// 让工作的对象开始工作, 点击开始按钮, 开始工作
connect(ui->startBtn, &QPushButton::clicked, work, &MyWork::working);

必须使用信号槽的方式来调用working()函数,不能直接调用

使用这种多线程方式,假设有多个不相关的业务流程需要放在子线程中被处理,那么就可以创建多个类似于MyWork的类,将业务流程放多类的公共成员函数中,然后将这个业务类的实例对象移动到对应的子线程中moveToThread()就可以了。这样就可实现在一个线程对象中做不同的任务