使用QT创建线程有两种方式,方式A使用moveToThread,方式B是直接继承QThread。差异主要在于方式A的槽函数将会在新线程中运行,而方式B的槽函数在旧线程中运行。
结论如下:
PS:旧线程在这里指主线程,而新线程指QThread创建出的线程。
相同点:
- 构造函数都是在旧线程中执行的
- 在QThread对象上直接调用的方法将在调用该方法的线程中执行
- QThread实例驻留在实例化它的旧线程中
不同点:
- 方式A的槽函数将会在新线程中运行,而方式B的槽函数在旧线程中运行
综上:使用方式B是需要注意,在不同的槽函数中操作成员变量时,实际上是在多个线程中进行操作,要检查这样做是否安全。除此之外使用两者的效果是相同的。
下面用实例来说明一下两者的差异。
Test类专门用来触发信号
class Test : public QObject
{
Q_OBJECT
public:
void startWork()
{
emit toStart();
}
signals:
void toStart();
};
方式A
CThreadA使用moveToThread的方式
class CThreadA : public QObject
{
Q_OBJECT
public:
CThreadA()
{
qDebug()<<"CThreadA construct:"<<QThread::currentThreadId();
}
void showMsg()
{
qDebug()<<"CThreadA showMsg:"<<QThread::currentThreadId();
}
void work()
{
qDebug()<<"CThreadA work:"<<QThread::currentThreadId();
}
public slots:
void doWork()
{
qDebug()<< "CThreadA doWork:" <<QThread::currentThreadId();
}
void printMsg()
{
qDebug()<< "CThreadA printMsg:" <<QThread::currentThreadId();
}
};
//主函数
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<<"main ThreadID:"<<QThread::currentThreadId();
Test test;
QThread thread;
CThreadA threadA;
threadA.moveToThread(&thread);
QObject::connect(&thread,SIGNAL(started()),&threadA,SLOT(doWork()));
QObject::connect(&test,SIGNAL(toStart()),&threadA,SLOT(printMsg()));
thread.start();
threadA.showMsg();
test.startWork();
return a.exec();
}
运行结果
方式B
CThreadB使用继承自QThread的方式
class CThreadB : public QThread
{
Q_OBJECT
void run()
{
qDebug()<< "CThreadB run:" <<QThread::currentThreadId();
work();
}
public:
CThreadB()
{
qDebug()<<"CThreadB construct:"<<QThread::currentThreadId();
}
void showMsg()
{
qDebug()<<"CThreadB showMsg:"<<QThread::currentThreadId();
}
void work()
{
qDebug()<<"CThreadB work:"<<QThread::currentThreadId();
}
public slots:
void printMsg()
{
qDebug()<< "CThreadB printMsg:" <<QThread::currentThreadId();
}
};
//主函数
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug()<<"main ThreadID:"<<QThread::currentThreadId();
Test test;
CThreadB threadB;
threadB.start();
threadB.showMsg();
QObject::connect(&test,SIGNAL(toStart()),&threadB,SLOT(printMsg()));
test.startWork();
return a.exec();
}