QThread模板

由于某些特殊原因,我们有时候使用线程需要QThread(信号-槽机制)。但是QThread需要继承它然后重写run函数,假如我们需要在线程中干100件事,那么就需要写100个QThread的子类,然后单独实现run函数,这样过于复杂。为此我想到使用std::function<>和模板来减少代码,写一个通用的模板线程。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifndef WORKERTHREADTEMPLATE_H_H
#define WORKERTHREADTEMPLATE_H_H

#include <QThread>
#include <functional>
using namespace std;
template <typename T,typename T1>
class WorkerThread :public QThread
{
public:
WorkerThread(QObject *parent = nullptr)
: QThread(parent)
{

}

void work( function<T (T1)> func,T1 arg)
{
m_Function=func;
m_arg=arg;
start();
}

T result(){return _result;}
protected:
virtual void run()
{

_result =m_Function(m_arg);

}
private:
T1 m_arg;
function<T (T1)> m_Function;
T _result;
};
#endif

这个模板只适用于一个参数的的非void返回类型,具体使用例子如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <QCoreApplication>
#include "workerthreadtemplate.h"
#include <QDebug>
static bool exitFlag=true;
bool myPrintf(QString str)
{
while(exitFlag){
qDebug()<<str;
QThread::sleep(2);
}
return true;

}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
WorkerThread<bool ,QString> workerThread;
workerThread.work(myPrintf,QString("测试"));
return a.exec();
}

如果传入的是类的成员非静态函数,那么需要使用std::bind。由于上述是模板类,使用起来局限性很大,无法传入任意个参数的函数。下面是改进版,使用std::bind和std::forward结合,std::bind可以简单理解为把一个函数指针和参数绑定起来,返回一个函数类型对象(std::function),参数第一个为要调用的函数指针。std::forward是保持参数传递过程中左右值属性不变。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <QThread>
#include <functional>

typedef std::function<void()> Functor;

class WorkerThread :public QThread
{
public:
explicit WorkerThread(QObject *parent = nullptr)
: QThread(parent)
{

}
virtual ~WorkerThread(){}

template <typename T,typename... Args>
void work(T func, Args... args){

m_function = std::bind(std::forward<T>(func), std::forward<Args>(args)...);

start();
}

protected:
virtual void run()
{

m_function();
exec();

}
private:
Functor m_function;


};

用法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
static bool exitFlag=true;
bool myPrintf(QString str,int size)
{
while(exitFlag){
qDebug()<<str<<size;
QThread::sleep(2);
}
return true;
}
int main()
{
WorkerThread *pWorkerThread=new WorkerThread();
pWorkerThread->work(myprintf,QString("test"),4);
}

QThread模板
http://yoursite.com/2019/03/22/QThread模板/
作者
还在输入
发布于
2019年3月22日
许可协议