关于多线程的话题这里说一点,主线程一般被称为gui线程,一切和界面相关的东西都应该在主线程,子线程一般负责复杂数据的计算,下面介绍qt多线程的两种用法。
QThread
Qt主要使用继承QThread重写run函数来完成多线程。
我们写了一个继承自QThread的MyThread,重写了它的run函数,之后创建MyThread对象,并让其start(),run函数就会运行在另一个线程里。
MyThread.h
#include <QThread>
#include <QDebug>
#include <windows.h>
class MyThread : public QThread
{
Q_OBJECT
public:
MyThread(){}
protected:
void run()
{
qDebug() << "run:" << GetCurrentThreadId();
}
};
main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug() << "main:" << GetCurrentThreadId();
MyThread thread;
thread.start();
return a.exec();
}
运行结果:
main: 7888
run: 4092
可以看到GetCurrentThreadId()输出了两个不同的进程id。
但是要注意,我们的MyThread对象是在主线程里的,只有它的run()函数是在新线程里运行的,它所拥有的槽函数都是在主线程里运行的。
movetothread
首先我们写一个在线程中工作的类
#include <QThread>
#include <QDebug>
#include <windows.h>
class ThreadWorker : public QObject
{
Q_OBJECT
public:
ThreadWorker(QWidget *parent = 0):QObject(parent){}
~ThreadWorker(){}
public slots:
void workerSlot()
{
qDebug() << "workerSlot:" << GetCurrentThreadId();
}
};
然后使用movetothread方法把它移动到新线程中,使用一个信号来调用它的槽。
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qDebug() << "main:" << GetCurrentThreadId();
QThread thread;//创建线程
thread.start();
ThreadWorker worker;//创建工作者
worker.moveToThread(&thread);//让工作者移动到新线程
QObject obj;//用于发送信号
QObject::connect(&obj,SIGNAL(destroyed()),&worker,SLOT(workerSlot()));
obj.deleteLater();//发射destroyed信号
return a.exec();
}
运行结果
main: 6532
workerSlot: 8680
可以看到,ThreadWorker整体都被移到新线程中,包括信号和槽。
其实connect函数还有第5个参数,这个参数决定了槽的执行方式,但是它会根据线程情况自动选择,所以这里就不讲了。
这种多线程使用的思想就如同ThreadWorker的名字一样,写一个负责繁杂工作的QObject,然后通过信号和槽的形式来对它发送指令或是接受结果。个人比较喜欢这种方式。