qt自己实现方便的线程管理类
  itL1q2DCWCoh 2023年11月02日 33 0


看本博客之前,可以先看看我这篇多线程博客:qt多线程使用方式_我是标同学的博客

为了实现方便使用的线程管理类,类似于QtConcurrent::run()函数,就很好用,而且还能直接给相应的实参。但是该方式不能随时停止线程,满足不了我们的使用,但是其思想还是可以借鉴的。

这里为了实现我们自己的方便的线程管理类,首先需要了解c++中模板函数的使用,可以看我这篇博客:c++模板的原理与使用_我是标同学的博客

使用方式:

接下来,是我们的线程管理类,功能是通过给定一个线程名字(作为唯一的标识符),待执行函数,函数的实参(可以多个),然后就能自动创建出该线程,而且可以进行停止等操作。使用如下(是不是很方便就使用啦,哈哈哈,不用去子类化QThread,重写run函数,等繁琐步骤了,此外qt自带的几个线程类都不太好用,而std标准库中的线程类就不错,可以直接给实参,但是使用起来还是不如qt库那么顺手好用,所以我才自己去写这个qt风格的线程库的):

//创建4个线程,分别给入不同的执行函数,以及实参,都能正确运行起来
    mTm->executeThread("xx", this, &MainWindow::print);
    mTm->executeThread("xx1", this, &MainWindow::print1, 9);
    mTm->executeThread("xx2", this, &MainWindow::print2, QString("nihao"));
    mTm->executeThread("xx3", this, &MainWindow::print3, 5, QString("yaya"));


    //停止指定的线程
    mTm->stopThread("xx");
    mTm->stopThread("xx1");

主要的工程代码(简单建立个工程就能运行了),如下:

1. mainwindow.cpp文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "thread/threadmanager.h"
#include "thread/thread.h"

#include <QTabBar>
#include <QDebug>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
        
    mTm = new ThreadManager(this);
    
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::print()
{
    for (int i = 0; i < 10000; ++i) {
        int j = 100000000;
        while (j--) {
            i = i;
        }
        qDebug()<<i;
    }
}

void MainWindow::print1(int a)
{
    for (int i = 0; i < 10000; ++i) {
        int j = 100000000;
        while (j--) {
            i = i;
        }
        qDebug()<<a;
    }
}

void MainWindow::print2(QString str)
{
    for (int i = 0; i < 10000; ++i) {
        int j = 100000000;
        while (j--) {
            i = i;
        }
        qDebug()<<str;
    }
}

void MainWindow::print3(int a, QString str)
{
    for (int i = 0; i < 10000; ++i) {
        int j = 100000000;
        while (j--) {
            i = i;
        }
        qDebug()<<a<<str;
    }
}



#include<iostream>
using namespace std;
#include<string>

void MainWindow::on_pushButton_clicked()
{
//    mTm->test(2);
    
    mTm->executeThread("xx", this, &MainWindow::print);
    mTm->executeThread("xx1", this, &MainWindow::print1, 9);
    mTm->executeThread("xx2", this, &MainWindow::print2, QString("nihao"));
    mTm->executeThread("xx3", this, &MainWindow::print3, 5, QString("yaya"));
}


void MainWindow::on_pushButton_2_clicked()
{
    mTm->stopThread("xx");
    mTm->stopThread("xx1");
}

2. mainwindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>


class ThreadManager;


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
    void print();
    void print1(int a);
    void print2(QString str);
    void print3(int a, QString str);
    
private slots:
    void on_pushButton_clicked();
    
    void on_pushButton_2_clicked();
    
private:
    Ui::MainWindow *ui;
    
    ThreadManager* mTm;
};
#endif // MAINWINDOW_H

 3. thread.h文件

(注意:不需要thread.cpp文件,因为该类是模板类,类的声明和定义都在一个.h文件里了,这是模板类必须要求的,否则编译报错,可以看我前面引用的文章)

#ifndef THREAD_H
#define THREAD_H

#include <QThread>
#include <QObject>
#include <QList>

//#include "threadmanager.h"



//模板类 或者 函数 声明和实现必须放在同一个头文件里
//
//写模板函数时,头文件和cpp文件不能分离,就是说你头文件里有模板的函数必须在头文件里实现,没有模板的函数可以放到cpp文件实现,模板类也如此
//
//用class或者typename都可以,一样的作用
template <class Return, class Class>
class Thread0 : public QThread
{
public:
    explicit Thread0(QObject *parent = nullptr): QThread{parent}
    {
        
    }
    
//    explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
    
    explicit Thread0(Class *object, Return (Class::*fn)(), QObject *parent = nullptr): QThread{parent}
    {
        mObject = object;
        mFun = fn;
    }
    
protected:
    void run()
    {
        //全部在这里处理子线程的复杂业务
        (mObject->*mFun)();
    }
    
private:
//    FunForThread mFunExe;
    
    //要想用模板定义成员变量,那么只能是整个类定义为模板类
    Class* mObject;
    Return (Class::*mFun)();
    int mNumberArgs = 0;
};


template <class Return, class Class, class Arg1>
class Thread1 : public QThread
{
public:
    explicit Thread1(QObject *parent = nullptr): QThread{parent}
    {
        
    }
    
    //    explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
    
    explicit Thread1(Class *object, Return (Class::*fn)(Arg1 arg1), Arg1 arg1, QObject *parent = nullptr): QThread{parent}
    {
        mObject = object;
        mFun = fn;
        mArg1 = arg1;
    }
    
protected:
    void run()
    {
        //全部在这里处理子线程的复杂业务
        (mObject->*mFun)(mArg1);
    }
    
private:
    //    FunForThread mFunExe;
    
    //要想用模板定义成员变量,那么只能是整个类定义为模板类
    Class* mObject;
    Return (Class::*mFun)(Arg1 arg1);
    Arg1 mArg1;
};


template <class Return, class Class, class Arg1, class Arg2>
class Thread2 : public QThread
{
public:
    explicit Thread2(QObject *parent = nullptr): QThread{parent}
    {
        
    }
    
    //    explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
    
    explicit Thread2(Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2), Arg1 arg1, Arg2 arg2, QObject *parent = nullptr): QThread{parent}
    {
        mObject = object;
        mFun = fn;
        mArg1 = arg1;
        mArg2 = arg2;

    }
    
protected:
    void run()
    {
        //全部在这里处理子线程的复杂业务
        (mObject->*mFun)(mArg1, mArg2);
    }
    
private:
    //    FunForThread mFunExe;
    
    //要想用模板定义成员变量,那么只能是整个类定义为模板类
    Class* mObject;
    Return (Class::*mFun)(Arg1 arg1, Arg2 arg2);
    Arg1 mArg1;
    Arg2 mArg2;    
};

template <class Return, class Class, class Arg1, class Arg2, class Arg3>
class Thread3 : public QThread
{
public:
    explicit Thread3(QObject *parent = nullptr): QThread{parent}
    {
        
    }
    
    //    explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
    
    explicit Thread3(Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3, QObject *parent = nullptr): QThread{parent}
    {
        mObject = object;
        mFun = fn;
        mArg1 = arg1;
        mArg2 = arg2;
        mArg3 = arg3;        
    }
    
protected:
    void run()
    {
        //全部在这里处理子线程的复杂业务
        (mObject->*mFun)(mArg1,mArg2,mArg3);
    }
    
private:
    //    FunForThread mFunExe;
    
    //要想用模板定义成员变量,那么只能是整个类定义为模板类
    Class* mObject;
    Return (Class::*mFun)(Arg1 arg1,Arg2 arg2,Arg3 arg3);
    Arg1 mArg1;
    Arg2 mArg2;
    Arg3 mArg3;    
};


template <class Return, class Class, class Arg1, class Arg2, class Arg3, class Arg4>
class Thread4 : public QThread
{
public:
    explicit Thread4(QObject *parent = nullptr): QThread{parent}
    {
        
    }
    
    //    explicit Thread(const Class *object, T (Class::*fn)(), QObject *parent = nullptr);
    
    explicit Thread4(Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4), Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg3 arg4, QObject *parent = nullptr): QThread{parent}
    {
        mObject = object;
        mFun = fn;
        mArg1 = arg1;
        mArg2 = arg2;
        mArg3 = arg3;
        mArg4 = arg4;          
    }
    
protected:
    void run()
    {
        //全部在这里处理子线程的复杂业务
        (mObject->*mFun)(mArg1,mArg2,mArg3,mArg4);
    }
    
private:
    //    FunForThread mFunExe;
    
    //要想用模板定义成员变量,那么只能是整个类定义为模板类
    Class* mObject;
    Return (Class::*mFun)(Arg1 arg1,Arg2 arg2,Arg3 arg3,Arg4 arg4);
    Arg1 mArg1;
    Arg2 mArg2;
    Arg3 mArg3;
    Arg4 mArg4;       
};



#endif // THREAD_H

4. threadmanager.cpp文件 

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>


class ThreadManager;


QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
    
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    
    void print();
    void print1(int a);
    void print2(QString str);
    void print3(int a, QString str);
    
private slots:
    void on_pushButton_clicked();
    
    void on_pushButton_2_clicked();
    
private:
    Ui::MainWindow *ui;
    
    ThreadManager* mTm;
};
#endif // MAINWINDOW_H

5. threadmanager.h文件

#ifndef THREADMANAGER_H
#define THREADMANAGER_H

#if 1

#include <QObject>
#include <QHash>
#include <QVariant>
#include <QDebug>

#include "thread.h"

class MainWindow;


class ThreadManager : public QObject
{
    Q_OBJECT
public:
    explicit ThreadManager(QObject *parent = nullptr);
    
    bool stopThread(QString name);


#if 1
    
    //这个用于去创建线程
    //    void executeThread(QString name, FunForThread funExe, QList<QVariant> args);
    
    //难度不能成员函数模板???只能全局函数模板或者类模板???
    //模板有3种形式:模板全局函数,模板类内成员函数,模板整个类(里面的成员变量和函数都可以是模板化了)
    //模板类 或者 函数 声明和实现必须放在同一个头文件里
    template <class Return, class Class>
    void executeThread(QString name, Class *object, Return (Class::*fn)())
    {
        Thread0<Return, Class>* t = new Thread0<Return, Class>(object, fn, this);
        
        if(mThreads.contains(name))
            stopThread(name);
        mThreads.insert(name, t);
        //        list.append((int)t);
        qDebug()<<this;
        //        list.append(t);
        qDebug()<<t;
        t->start();
    }
    
    template <class Return, class Class, typename Arg1>
    void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1), Arg1 arg1)
    {
        Thread1<Return, Class, Arg1>* t = new Thread1<Return, Class, Arg1>(object, fn, arg1, this);
        
        if(mThreads.contains(name))
            stopThread(name);
        mThreads.insert(name, t);
        t->start();
    }
    
    template <class Return, class Class, typename Arg1, typename Arg2>
    void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2), Arg1 arg1, Arg2 arg2)
    {
        Thread2<Return, Class, Arg1, Arg2>* t = new Thread2<Return, Class, Arg1, Arg2>(object, fn, arg1, arg2, this);
        
        if(mThreads.contains(name))
            stopThread(name);
        mThreads.insert(name, t);
        t->start();
    }
    
    template <class Return, class Class, typename Arg1, typename Arg2, typename Arg3>    
    void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3), Arg1 arg1, Arg2 arg2, Arg3 arg3)
    {
        Thread3<Return, Class, Arg1, Arg2, Arg3>* t = new Thread3<Return, Class, Arg1, Arg2, Arg3>(object, fn, arg1, arg2, arg3, this);
        
        if(mThreads.contains(name))
            stopThread(name);
        mThreads.insert(name, t);
        t->start();
    }
    
    template <class Return, class Class, typename Arg1, typename Arg2, typename Arg3, typename Arg4>    
    void executeThread(QString name, Class *object, Return (Class::*fn)(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4), Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4)
    {
        Thread4<Return, Class, Arg1, Arg2, Arg3, Arg4>* t = new Thread4<Return, Class, Arg1, Arg2, Arg3, Arg4>(object, fn, arg1, arg2, arg3, arg4, this);
        
        if(mThreads.contains(name))
            stopThread(name);
        mThreads.insert(name, t);
        t->start();
    }
#endif
    
    
private:
    //    template <class Return, class Class> 成员变量不能单独设为模板变量
    QHash<QString, QThread*> mThreads;
    
};

#endif

#endif // THREADMANAGER_H
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  0m5NSAqMb1kD   2023年12月08日   29   0   0 MySQLMySQLcici
  5a6ysVJd64PV   2023年12月12日   31   0   0 ciredisciredis
itL1q2DCWCoh