QThread 应用浅析

Qt的一个普遍应用,是用于进行交互式软件开发,往往是需要多任务后台运行,以免阻塞UI界面,这就需要用到多线程,便捷的多线程实现,可以采用C++标准库 std::thread 或 boost:Thread 以及QThread。由于我们本身是使用Qt平台开发,使用QThread是兼容性也是最好,也方便移植,故Qt平台下推荐使用Qt实现多线程方法。

QThread 一般有两种实现方式,一种是继承自QThread,并重载run函数,这种方式的缺陷是,所有的操作必须在run()中进行,并且不被官方建议如此使用;另外一种是继承自QObject,然后moveToThread(),这样QObject的所有方法就会在次线程中运行,此种方式为官方所推荐。此外,如果需要多线程实现QTimer/QTcpSocket等,使用moveToThread方式是最为科学合理的。

下面是一个示例程序,定义一个MyWork类,一个调用类MyTest,通过MyTest类调用MyWork类方法,并且在次线程中运行。

头文件

#include <QObject>
#include <QThread>

class MyWorker : public QObject
{
	Q_OBJECT

public:
	MyWorker();
	~MyWorker();

public slots:

	void runWork_1();
	void runWork_2();
	void runWork_3();
};

class MyTest : public QObject
{
	Q_OBJECT

public:
	MyTest();
	~MyTest();

	MyWorker* work;
	QThread qt;

	void init();
	void test();

signals:

	void sigWork_1();
	void sigWork_2();
	void sigWork_3();
};

源文件.cpp

MyWorker::MyWorker()
{
	printf("MyWorker: current thread id: %p\n", QThread::currentThreadId());
}
MyWorker::~MyWorker()
{
	printf("~MyWorker: current thread id: %p\n", QThread::currentThreadId());
}

void MyWorker::runWork_1()
{
	printf("1. current thread id: %p\n", QThread::currentThreadId());
}
void MyWorker::runWork_2()
{
	printf("2. current thread id: %p\n", QThread::currentThreadId());
}
void MyWorker::runWork_3()
{
	printf("3. current thread id: %p\n", QThread::currentThreadId());
}

MyTest::MyTest()
{
	printf("MyTest: current thread id: %p\n", QThread::currentThreadId());

	init();
}
MyTest::~MyTest()
{
	printf("~MyTest: current thread id: %p\n", QThread::currentThreadId());
}

void MyTest::init()
{
	work = new MyWorker;
	work->moveToThread(&qt);
	connect(this, &MyTest::sigWork_1, work, &MyWorker::runWork_1);
	connect(this, &MyTest::sigWork_2, work, &MyWorker::runWork_2);
	connect(this, &MyTest::sigWork_3, work, &MyWorker::runWork_3, Qt::DirectConnection);
	connect(&qt, &QThread::finished, work, &QObject::deleteLater);
	qt.start();
}

void MyTest::test()
{
	printf("MyTest: current thread id: %p\n", QThread::currentThreadId());

	sigWork_1();
	QThread::sleep(1);

	sigWork_2();
	QThread::sleep(1);

	sigWork_3();
	QThread::sleep(1);

	qt.quit();
	qt.wait();

	printf("finished!\n");
}

在main.cpp中测试

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

//     MainWin w;
//     w.show();

    MyTest mt;
    mt.test();

    return a.exec();
}

下图为测试结果:

可以看到:

1) MyWorker在主线程中创建

2) runWork_1() 与 runWork_2() 方法均在次线程中执行,并且 MyWorker 在次线程中被析构

3) runWork_3() 在主线程中执行,这是因为 使用了 Qt::DirectConnection,槽函数将立即在当前线程中执行,本例中在主线程中运行。因此,如果对QTimer、QTcpSocket等使用多线程,尽量不要使用 Qt::DirectConnection 连接方式。

综上,使用 moveToThread 后,当前对象QObject被移动到QThread中,所有方法可通过发送signal来调用,并会在QThread中执行,完美实现异步执行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值