Qt用了好久了,最近才刚知道有这个概念,惭愧。。。。。。
核心就一句话:对象是在哪个线程中构造的,就只能在创建它的线程中被调用。
在QT中每个线程都有自己的事件循环EventLoop,把对象移动到哪个线程,那么当触发这个对象的槽函数时,槽函数就在这个线程中(的event loop)运行。所谓moveToThread就是指定槽函数由哪个线程执行。
如果非要在其他线程中使用,就需要moveToThread(thread)方法,把它移动到对应的线程中。
用代码来说明更方便些:
#include <QThread>
#include <QTimer>
#include <QDebug>
#include <QCoreApplication>
// 线程B的Worker对象
class WorkerB : public QObject
{
Q_OBJECT
public slots:
void handleTimeout()
{
invokeCount++;
qDebug() << "槽函数执行线程id:" << QThread::currentThreadId() << " 执行次数:" << invokeCount;
if (invokeCount >= 10)
{
qDebug() << "invokeCount = 10, quit";
emit app_quit();
}
}
signals:
void app_quit();
private:
int invokeCount = 0; // 新增成员变量,用于记录槽函数的调用次数,用于测试多线程异步调用的
};
// 线程A的定时器管理
class ThreadA : public QThread
{
Q_OBJECT
protected:
void run() override
{
WorkerB workerB;
// 将workerB移动到线程B
workerB.moveToThread(qApp->thread()); // 假设主线程是线程B
// 在当前线程创建定时器timer,这样它就属于这个线程,而不能使用m_timer
QTimer timer;
// 连接定时器信号到线程B的槽
connect(&timer, &QTimer::timeout, &workerB, &WorkerB::handleTimeout);
connect(&workerB, &WorkerB::app_quit, this, &ThreadA::quit);
connect(&workerB, &WorkerB::app_quit, &workerB, &WorkerB::deleteLater); // 确保workerB在退出时被删除
timer.start(1000); // 1秒触发一次
exec(); // 启动事件循环
}
private:
void quit()
{
qDebug() << "线程A退出";
QThread::quit();
}
private:
QTimer m_timer;
};
// 主程序
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
// 这里调用了ThreadA的构造方法,其成员m_timer同时被创建了,注意现在是在主线程中,所以在线程亲和性上,m_timer属于主线程
// 这里挺绕的,m_timer是ThreadA这个类的成员变量,但它不属于threadA这个对象所代表的线程
// 总之就是,从类成员的角度来说,m_timer是ThreadA的成员变量,但从线程亲和性上来说,它属于主线程
ThreadA threadA;
threadA.start();
QObject::connect(&threadA, &ThreadA::finished, []()
{
qDebug() << "主线程(B)退出";
QCoreApplication::quit(); });
int ret = a.exec();
qDebug() << "事件循环退出";
return ret;
}
#include "MultiThreadAsync.moc"
919

被折叠的 条评论
为什么被折叠?



