关于QEventLoop的理解

情况一

		QTimer* timer = new QTimer;
	timer->start(1000);

	int t = 0;
	QObject::connect(timer, &QTimer::timeout, this, [=]() {

		 QEventLoop loop;
		qDebug() << "chufa";
		QTimer::singleShot(3000, this, [&]() {
			qDebug() << "quit";
			loop.quit();
			});
		loop.exec();
		qDebug() << u8"执行完成";
		});
		
测试结果
由于timer属于主线程,此时连接的类型为Qt::DirectConnection
与其连接的槽函数会立即调用,应该是回调函数的形式,执行线程为信号发送的线程
此时,信号会等待槽函数执行完成后再发送一次信号。这并不是线程被阻塞,而是由于DirectConnection连接方式导致直接调用槽函数,
槽函数却需要等待loop.quit()后才执行完成,即这个信号才会执行完成。然后才会继续触发信号。期间timer不会计时。

情况二

		QTimer* timer = new QTimer;
	timer->start(1000);

	int t = 0;
	QObject::connect(timer, &QTimer::timeout, this, [=]() {

		 QEventLoop loop;
		qDebug() << "chufa";
		QTimer::singleShot(3000, this, [&]() {
			qDebug() << "quit";
			loop.quit();
			},Qt::QueuedConnection);
		loop.exec();
		qDebug() << u8"执行完成";
		});
仅是改变信号槽的连接方式为QueuedConnection
此时只要信号触发就会执行代码到loop.exec()处,因为QueuedConnection连接方式为队列
但是需要注意的是
即使某一次触发调用了loop.quit(),但是只要还存在其他的子事件循环,则后面的代码不会执行。并且由于这个时间差的关系,还会导致报错堆栈溢出的错误。从而导致程序挂掉。

如果timer对象在子线程,结果和上面一致
因此此种方式不可取。

情况三


	QTimer* timer = new QTimer;
	timer->start(1000);

	QThread* thread = new QThread();
	timer->moveToThread(thread);
	thread->moveToThread(thread);
	connect(thread, &QThread::started, timer, QOverload<>::of(&QTimer::start));
	thread->start();

	int t = 0;
	QObject::connect(timer, &QTimer::timeout, this, [=]() {

		if (loop.isRunning()) return;
		qDebug() << "chufa";
		QTimer::singleShot(3000, this, [&]() {
			qDebug() << "quit";
			loop.quit();
			});
		loop.exec();
		qDebug() << u8"执行完成";
		});

timer处于子线程,槽函数处于线程,连接方式为QueuedConnection
loop为成员变量 QEventLoop loop
此时,即使信号多次触发,但是只要上一次的isRunning为true,则会自动丢弃该次触发。从而保证运行安全
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值