moveToThread函数的功能:给多个任务(比如显示多个界面)各分配一个线程去执行。这样就避免了自定义好多个类继承自QThread类,从而可以避免冗余。
翻译:更改此对象(继承自QObject类)及其子对象(继承自QObject类的子类,比如QDialog、QWidget)的线程关联关系。如果对象有父对象,则不能移动该对象。事件处理将在targetThread中继续。
要将对象移动到主线程,请使用QApplication::instance()来检索指向当前应用程序的指针,然后使用QApplication::thread()来检索应用程序所在的线程。
如果targetThread为0,则该对象及其子对象的所有事件处理都将停止。
使用moveToThread函数的流程如下:
1、创建一个类继承自QObject类或其子类,并在其中定义所要执行的多个任务,执行多个任务就要定义相应的信号。
2、任务通过moveToThread指定所要执行的线程。
3、线程通过start启动
4、通过信号与槽机制触发线程的执行
示例代码:
my_task.h
#ifndef MY_TASK_H
#define MY_TASK_H
#include <QObject>classMy_Task:public QObject
{Q_OBJECTpublic:
explicit My_Task(QObject *parent = nullptr);voidtask_01();voidtask_02();signals:voidtask_01_signal(int value);voidtask_02_signal(int value);publicslots:};
#endif // MY_TASK_H
my_task.cpp
#include "my_task.h"
#include "unistd.h"My_Task::My_Task(QObject *parent):QObject(parent){}voidMy_Task::task_01(){
int i=0;for(;;){
emit task_01_signal(i++);sleep(1);sleep(1);if(i>10){break;}}}voidMy_Task::task_02(){
int i=0;for(;;){
emit task_02_signal(i++);sleep(1);if(i>10){break;}}}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(newUi::MainWindow){
ui->setupUi(this);
task1 =newMy_Task;// 不要给定父对象
my_thread1 =newQThread(this);
task1->moveToThread(my_thread1);
my_thread1->start();connect(ui->btnStart,&QPushButton::clicked,task1,&My_Task::task_01);connect(task1,&My_Task::task_01_signal,[=](int val){
ui->lcdNumber->display(QString::number(val));});
task2 =newMy_Task;// 不要给定父对象
my_thread2 =newQThread(this);
task2->moveToThread(my_thread2);
my_thread2->start();connect(ui->btnStart,&QPushButton::clicked,task2,&My_Task::task_02);connect(task2,&My_Task::task_02_signal,[=](int val){
ui->lcdNumber_2->display(QString::number(val));});connect(this,&QObject::destroyed,[=](){
my_thread1->exit();
my_thread1->wait();delete task1;});connect(this,&QObject::destroyed,[=](){
my_thread2->exit();
my_thread2->wait();delete task2;});}MainWindow::~MainWindow(){delete ui;}
运行效果如下,程序有问题,并非并发,有个线程会卡住。
思考改进:使用定时器代替sleep,在定时器事件中执行任务函数
改进后代码如下,
my_task.h
#ifndef MY_TASK_H
#define MY_TASK_H
#include <QObject>classMy_Task:public QObject
{Q_OBJECTpublic:
explicit My_Task(QObject *parent = nullptr);voidtask_01();voidtask_02();signals:voidtask_01_signal(int value);voidtask_02_signal(int value);publicslots:private:
int value1=0;
int value2=0;};
#endif // MY_TASK_H
my_task.cpp
#include "my_task.h"
#include "unistd.h"My_Task::My_Task(QObject *parent):QObject(parent){}voidMy_Task::task_01(){if(value1>10){return;}
emit task_01_signal(value1++);}voidMy_Task::task_02(){if(value2>10){return;}
emit task_02_signal(value2++);}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(newUi::MainWindow){
ui->setupUi(this);
task1 =newMy_Task;// 不要给定父对象
my_thread1 =newQThread(this);
task1->moveToThread(my_thread1);
my_thread1->start();connect(task1,&My_Task::task_01_signal,[=](int val){
ui->lcdNumber->display(QString::number(val));});
task2 =newMy_Task;// 不要给定父对象
my_thread2 =newQThread(this);
task2->moveToThread(my_thread2);
my_thread2->start();connect(task2,&My_Task::task_02_signal,[=](int val){
ui->lcdNumber_2->display(QString::number(val));});}MainWindow::~MainWindow(){
my_thread1->quit();
my_thread1->wait();
my_thread2->quit();
my_thread2->wait();delete task1;delete task2;delete ui;}voidMainWindow::timerEvent(QTimerEvent *event){if(event->timerId()== timer1){
task1->task_01();
task2->task_02();}}voidMainWindow::on_btnStart_clicked(){/* startTimer()功能是启动计时器并返回计时器标识符,如果不能启动计时器则返回零 *//* 计时器事件将每间隔 1000 毫秒发生一次,直到killTimer()被调用。*/
timer1 =startTimer(1000);}
运行效果如下,点击按钮后,第一下会慢。
版权归原作者 xuechanba 所有, 如有侵权,请联系我们删除。