Qt 多线程第二种实现方式 继承QObject moveToThread

上一篇 我们说了第一种实现方式 继承QThread 重写run方法
https://blog.csdn.net/weixin_42837024/article/details/81409136

这一篇我们说一下比直接继承QThread更为灵活,就是直接继承QObject实现多线程

继承QObject实现多线程

QObject的线程转移函数是:void moveToThread(QThread * targetThread) ,通过此函数可以把一个顶层Object(就是没有父级)转移到一个新的线程里。

  • 我们准备一个 继承QObject的类: myThread * m_thread = new myThread();
  • new一个QThread QThread * thread = new QThread();
  • m_thread->moveToThread(thread);
  • connect(thread,&QThread::finished,thread,&QThread::deleteLater);
  • connect(thread,&QThread::finished,m_thread,&myThread::deleteLater);

还有一点是 想要在新线程里执行,必须要用信号和槽,否则还是在主线程中运行

测试一下 m_thread->doWork(); 直接执行会出现什么情况?

mythread.h

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>
#include <QMutex>


class myThread :public QObject
{
    Q_OBJECT
public:
    myThread(QObject* parent = NULL);

    void doWork();

    void stopThread();
signals:
    void currentProgress(int value);

private:
    bool m_isRun = true;
    QMutex *m_mutex;
};

#endif // MYTHREAD_H

mythread.cpp

#include "mythread.h"
#include <QDebug>
myThread::myThread(QObject *parent)
{
    qDebug()<<"construction ThreadID:"<<QThread::currentThreadId();
    m_mutex = new QMutex();
}

void myThread::doWork()
{
    for(int i = 0;i<=100;i+=10)
    {
        if(!m_isRun)
            return;

        qDebug()<<"doWork() ThreadID:"<<QThread::currentThreadId();

        emit currentProgress(i);

        QThread::msleep(200);
    }
    qDebug()<<"doWork over";

}



void myThread::stopThread()
{
    QMutexLocker(*m_mutex);
    m_isRun = false;
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "mythread.h"
#include <QThread>
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
signals:
    void startWork();

private slots:


    void receiveProgress(int value);


    void on_doWorkButton_clicked();

private:
    Ui::Widget *ui;
    QThread* thread;
    myThread* m_thread;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    qDebug()<<"UI widget ThreadId:"<<QThread::currentThreadId();

    ui->progressBar->setValue(0);


    m_thread = new myThread();
    thread = new QThread();
    m_thread->moveToThread(thread);

    connect(m_thread,&myThread::currentProgress,this,&Widget::receiveProgress);


   // connect(this,&Widget::startWork,m_thread,&myThread::doWork);


    connect(thread,&QThread::finished,thread,&QThread::deleteLater);
    connect(thread,&QThread::finished,m_thread,&myThread::deleteLater);

}

Widget::~Widget()
{

    if(thread->isRunning())
        m_thread->stopThread();

    thread->quit();
    thread->wait();


    delete ui;
}


void Widget::receiveProgress(int value)
{
    ui->progressBar->setValue(value);
}


void Widget::on_doWorkButton_clicked()
{

   thread->start();


   m_thread->doWork();



}

这里写图片描述

线程Id 一模一样 说明根本没有进入线程

因为这是在主线程中调用的。。。
所以我们改为用信号和槽

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    qDebug()<<"UI widget ThreadId:"<<QThread::currentThreadId();

    ui->progressBar->setValue(0);


    m_thread = new myThread();
    thread = new QThread();
    m_thread->moveToThread(thread);

    connect(m_thread,&myThread::currentProgress,this,&Widget::receiveProgress);


    connect(this,&Widget::startWork,m_thread,&myThread::doWork);//建立信号和槽的连接


    connect(thread,&QThread::finished,thread,&QThread::deleteLater);
    connect(thread,&QThread::finished,m_thread,&myThread::deleteLater);

}

Widget::~Widget()
{

    if(thread->isRunning())
        m_thread->stopThread();

    thread->quit();
    thread->wait();


    delete ui;
}


void Widget::receiveProgress(int value)
{
    ui->progressBar->setValue(value);
}


void Widget::on_doWorkButton_clicked()
{

   thread->start();


  emit startWork();//发送信号



}

这里写图片描述

这次就是在新的线程中执行的了

    connect(thread,&QThread::finished,thread,&QThread::deleteLater);
    connect(thread,&QThread::finished,m_thread,&myThread::deleteLater);

这个必须要连接否则会造成内存泄漏

析构里面也要处理

Widget::~Widget()
{

    if(thread->isRunning())//如果正在运行
        m_thread->stopThread();//停止

    thread->quit();//退出
    thread->wait();//阻塞等待退出


    delete ui;
}
        98年菜鸡一枚,如果错误请大佬多多指教多谢多谢!

猜你喜欢

转载自blog.csdn.net/weixin_42837024/article/details/81411178
今日推荐