Qt多线程(继承QThread、QObject简单实例代码对比)

以文件复制为例作简单对比
Qt多线程(继承QThread、QObject简单实例代码对比)_第1张图片

一.继承QThread

#ifndef Thread_CopyFile_H
#define Thread_CopyFile_H

#include 

class Thread_CopyFile : public QThread
{
    Q_OBJECT
public:
    Thread_CopyFile(QObject * parent = 0);

protected:
    void run(); // 新线程入口

signals:
    void percentCopied(double percent);
    void finished();
    void errorOccurred();

public slots:
    void cancelCopy();

private:
    bool m_canceled;
};

#endif // Thread_CopyFile_H
#include "Thread_CopyFile.h"
#include 
#include 
#include "common.h"
#include 

Thread_CopyFile::Thread_CopyFile(QObject *parent)
    : QThread(parent)
{
    // 新线程的初始化不要放在这里
}

void Thread_CopyFile::run()
{
    // 新线程入口
    // 初始化和操作放在这里
    m_canceled = false;
    QFile src(SrcFile);
    QFile cpy(CpyFile);
    qint64 srcSize = QFileInfo(src).size();//9000
    int bytesWritten = 0;
    if (srcSize==0 || !src.open(QFile::ReadOnly))
    {
        emit errorOccurred();
        return;
    }
    if (cpy.exists())
    {
        cpy.resize(0);//清空目标txt内容
    }
    if (!cpy.open(QFile::WriteOnly))
    {
        src.close();
        emit errorOccurred();
        return;
    }
    qDebug()<<"curThreadId()=="<<QThread::currentThreadId();
    while (!src.atEnd())
    {
        if (m_canceled)
        {
            src.close();
            cpy.close();
            cpy.remove();
            return;
        }
        msleep(8);
        qint64 wrt = cpy.write(src.readLine());//9
        if (wrt < 0)
        {
            emit errorOccurred();
            src.close();
            cpy.close();
            cpy.remove();
            return;
        }
        bytesWritten += wrt;
        emit percentCopied(bytesWritten*1.0/srcSize);//返回百分比
    }
    src.close();
    cpy.close();
    emit finished();
}

void Thread_CopyFile::cancelCopy()
{
    m_canceled = true;
}

二.继承QObject

#ifndef OBJECT_COPYFILE_H
#define OBJECT_COPYFILE_H

#include 

class Object_CopyFile : public QObject
{
    Q_OBJECT
public:
    explicit Object_CopyFile(QObject *parent = 0);

signals:
    void percentCopied(double percent);
    void finished();
    void errorOccurred();

public slots:
    void startCopying();
    void cancelCopying();

private:
    bool m_canceled;
};

#endif // FILECOPIER_H
#include "Object_CopyFile.h"
#include "common.h"
#include 
#include 
#include 
#include 

Object_CopyFile::Object_CopyFile(QObject *parent) : QObject(parent)
{
    // 这个类与多线程的实现没有直接的关系,它就老老实实地做好自己的事情
    m_canceled = false;
}

void Object_CopyFile::startCopying()
{
    qDebug()<<"curThreadId()=="<<QThread::currentThreadId();
    m_canceled = false;
    QFile src(SrcFile);
    QFile cpy(CpyFile);
    qint64 srcSize = QFileInfo(src).size();
    int bytesWritten = 0;
    if (srcSize==0 || !src.open(QFile::ReadOnly))
    {
        emit errorOccurred();
        return;
    }
    if (cpy.exists())
    {
        cpy.resize(0);
    }
    if (!cpy.open(QFile::WriteOnly))
    {
        src.close();
        emit errorOccurred();
        return;
    }

    while (!src.atEnd())
    {
        if (m_canceled)
        {
            src.close();
            cpy.close();
            cpy.remove();
            return;
        }
        QThread::msleep(8);
        qint64 wrt = cpy.write(src.readLine());
        if (wrt < 0)
        {
            emit errorOccurred();
            src.close();
            cpy.close();
            cpy.remove();
            return;
        }
        bytesWritten += wrt;
        emit percentCopied(bytesWritten*1.0/srcSize);
    }
    src.close();
    cpy.close();
    emit finished();
}

void Object_CopyFile::cancelCopying()
{
    m_canceled = true;
}

三.调用

private:
    Ui::MainWindow *ui;
    Thread_CopyFile *m_Thr; // 用于复制文件的子线程

    Object_CopyFile *m_Obj; // 用户复制文件的类
    QThread *m_Thread;      // m_Obj将被移动到此线程执行

    Object_CopyFile *m_Obj2;// 用户复制文件的类
//方式一 自定义线程,继承QThread重写run()函数,复制任务在run中完成
    m_Thr = new Thread_CopyFile(this);
    connect(m_Thr, SIGNAL(errorOccurred()),this, SLOT(errorHandleSlot()));
    connect(m_Thr, SIGNAL(percentCopied(double)),this, SLOT(updateCopyProgress(double)));
    connect(m_Thr, SIGNAL(finished()),this, SLOT(copyFinishSlot()));

    //方式二 继承QObject,使用MoveToThread
    m_Obj = new Object_CopyFile; // 这个实例要负责复制任务,不要设置parent
    m_Thread = new QThread; // 子线程,本身不负责复制
    // 将实例移动到新的线程,实现多线程运行

    connect(this, SIGNAL(startCopyRsquested()), m_Obj, SLOT(startCopying()));
    connect(this, SIGNAL(cancelCopuRequested()), m_Obj, SLOT(cancelCopying()));
    connect(m_Obj, SIGNAL(errorOccurred()),this, SLOT(errorHandleSlot()));
    connect(m_Obj, SIGNAL(percentCopied(double)),this, SLOT(updateCopyProgress(double)));
    connect(m_Obj, SIGNAL(finished()),this, SLOT(copyFinishSlot()));
    m_Obj->moveToThread(m_Thread);
    //connect(m_childThread,SIGNAL(started()),m_copier,SLOT(startCopying()));  //开启线程槽函数
    //m_Thread->start(); //启动子线程

    //单线程(继承QObject,不使用MoveToThread)
    m_Obj2 = new Object_CopyFile;
    connect(this, SIGNAL(startCopyRsquested2()), m_Obj2, SLOT(startCopying()));
    connect(this, SIGNAL(cancelCopuRequested2()), m_Obj2, SLOT(cancelCopying()));
    connect(m_Obj2, SIGNAL(errorOccurred()),this, SLOT(errorHandleSlot()));
    connect(m_Obj2, SIGNAL(percentCopied(double)),this, SLOT(updateCopyProgress(double)));
    connect(m_Obj2, SIGNAL(finished()),this, SLOT(copyFinishSlot()));
...
void MainWindow::on_btnCopy1_clicked()
{
    m_Thr->start(); // 复制文件的新线程开始(用start()自动调用run())
}

void MainWindow::on_btnCopy2_clicked()
{
    qDebug()<<"Main btnCopy2 threadId()=="<<QThread::currentThreadId();
    m_Thread->start();   //需start才能有效传信号槽
    emit startCopyRsquested();  //m_childThread不start时槽函数不响应
}

void MainWindow::on_btnCopy3_clicked()
{
    qDebug()<<"Main btnCopy3 threadId()=="<<QThread::currentThreadId();
    emit startCopyRsquested2();
}

四.代码

以文件复制为例将继承QThread、QObject,两种Qt多线程方式作简单对比

五.参考链接

Github某星夜之夏
Qt使用多线程的一些心得——2.继承QObject的多线程使用方法

你可能感兴趣的:(Qt,QThread,qt,开发语言)