上一篇 我们说了第一种实现方式 继承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年菜鸡一枚,如果错误请大佬多多指教多谢多谢!