赞
踩
Qt中主线程负责界面显示和窗口控件的数据更新,子线程负责逻辑业务处理和数据计算,子线程不能对窗口有任何操作,子线程可通过信号槽来将数据传递给主线程。
1、子线程继承QThread
子线程继承QThread,然后重写run()函数来执行子线程
每一个子业务逻辑都可继承一个QThread来实现多线程
- m_thread = new MyThread;
- connect(m_thread, &MyThread::signalsThreadCalNum, this, [=](int num){
- ui->label->setNum(num);
- });
- connect(ui->pushButton_start, &QPushButton::clicked, m_thread, [=](){
- m_thread->start();
- });
- connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
- m_thread->Stop();
- });
- class MyThread:public QThread
- {
- Q_OBJECT
- //....
- protected:
- void run();
- }
-
- void MyThread::run()
- {
- int n = 0;
- while(n < 100000)
- {
- emit signalsThreadCalNum(n++);
- QThread::usleep(1);
- }
- }
2、使用moveToThread
(1)任务类Task需要继承QObject,然后写一个执行任务的函数。
(2)创建一个QThread线程,然后调用moveToThread将对象移动到创建的子线程对象中
(3)启动子线程即可
- //创建子线程
- m_thread = new QThread;
- m_work = new MyWork;
- //将工作的类对象转移到创建的子线程对象中
- m_work->moveToThread(m_thread);
-
- //启动线程
- m_thread->start();
- //这种写法是错误的,界面卡顿,个人理解:接受者是this,相当于mainwiodnw调用
- // connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
- // m_work->Work();
- // });
- //ok
- connect(ui->pushButton_start, &QPushButton::clicked, m_work, [=](){
- m_work->Start();
- });
-
- connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
- m_work->Stop();
- });
- connect(m_work, &MyWork::signalsThreadCalNum, this, [=](int num){
- ui->label->setNum(num);
- });
- class MyWork:public QObject
- {
- //......
- }
-
- void MyWork::Work()
- {
- int n = 0;
- while(n < 1000)
- {
- if(m_stop)
- break;
- emit signalsThreadCalNum(n++);
- QThread::usleep(1);
- }
- }
3、使用QtConcurrent
(1)pro中需要加上 QT += concurrent
(2)任务类中重写run()函数
- MyThread *mythread = new MyThread;
- connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
- QtConcurrent::run(mythread, &MyThread::Work);
- });
- connect(mythread, &MyThread::signalsThreadCalNum, this, [=](int num){
- ui->label->setNum(num);
- });
- connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
- mythread->Stop();
- });
- void MyThread::Work()
- {
- m_stop = false;
- int n = 0;
- while(n < 100000)
- {
- if(m_stop)
- break;
- emit signalsThreadCalNum(n++);
- QThread::usleep(1);
- }
- }
4、使用线程池
使用QRunnable和QThreadPool
(1)任务类需要继承QRunnable,需要使用信号槽的话可多重继承QObject
(2)重写run函数
(3)使用QThreadPool::globalInstance()->start(QRunable *)来启动线程池
- // 线程池初始化,设置最大线程池数
- QThreadPool::globalInstance()->setMaxThreadCount(4);
-
- //创建任务
- MyThread *mythread = new MyThread;
-
- //start启动线程池
- connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
- QThreadPool::globalInstance()->start(mythread);
- mythread->Start();
- });
- connect(mythread, &MyThread::signalsThreadCalNum, this, [=](int num){
- ui->label->setNum(num);
- });
- connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
- mythread->Stop();
- });
- /*
- * 线程池使用需要继承QRunnable
- */
- class MyThread : public QObject, public QRunnable
- {
- //.....
- }
-
- MyThread::MyThread(QObject *parent) : QObject(parent), QRunnable()
- {
- setAutoDelete(true);
- }
-
- void MyThread::run()
- {
- m_stop = false;
- int n = 0;
- while(n < 100000)
- {
- if(m_stop)
- break;
- emit signalsThreadCalNum(n++);
- QThread::usleep(1);
- }
- }
5、线程池中可不采用多重继承QObject,可采用
QMetaObject::invokeMethod来实现
mainwindow.h中添加
-
-
- Q_INVOKABLE void Show(int num);
mainwindow.cpp
-
-
- //mainwindow.cpp
-
- // 线程池初始化,设置最大线程池数
- QThreadPool::globalInstance()->setMaxThreadCount(4);
-
- //创建任务
- MyThread *mythread = new MyThread(this);
-
- //start启动线程池
- connect(ui->pushButton_start, &QPushButton::clicked, this, [=](){
- QThreadPool::globalInstance()->start(mythread);
- mythread->Start();
- });
-
- connect(ui->pushButton_stop, &QPushButton::clicked, this, [=](){
- mythread->Stop();
- });
-
- void MainWindow::Show(int num)
- {
- ui->label->setNum(num);
- }
子线程中
- void MyThread::run()
- {
- m_stop = false;
- int n = 0;
- while(n < 100000)
- {
- // if(m_stop)
- // break;
- QMetaObject::invokeMethod(m_pObj, "Show", Q_ARG(int, n++));
- //emit signalsThreadCalNum(n++);
- QThread::usleep(1);
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。