在进行桌面应用程序开发的时候,假设应用程序在某些情况下需要处理比较复杂的逻辑,如果只有一个线程去处理,就会导致窗口卡顿,无法处理用户的相关操作。
这种情况下就需要使用多线程,其中一个线程处理窗口事件,其他线程进行逻辑运算,多个线程各司其职,不仅可以提高用户体验还可以提升程序的执行效率。
Qt对多线程使用提供了多种方法,除了最简单的继承QThread,重写run函数外,还有一种比较常用且好用的方法:moveToThread
1.moveToThread理解
moveToThread允许用户自己封装一个“Worker”的类(Worker必须继承于QObject),
它可以将所有希望子线程处理的函数定义成自身的成员槽函数,通过信号槽方式,使其在子线程运行,且不影响主线程UI。
"Worker"类可以理解成一个“工作机”,它可以组合到任意一个有实际意义的类中,该工作机负责处理耗时的非UI工作。
2.实例使用
场景:在一个拥有定时测量功能的NIBP类中,由于包含许多高频定时器,需要将这些定时测量的定时器放在子线程中去做,防止测量过程中阻塞主线程UI- // NIBP.h 文件
- class NIBP : public QObject
- {
- public:
- void StartNoramlTest(); //开始测量
- void EndTest(); //结束测量
- signals:
- void SignalStartTest(); //开始测量信号
- void SignalEndTest(); //结束测量信号
- private:
- NIBPWorker *mWorker;
- QThread *mWorkerThread;
- };
复制代码 "Worker"类的作用就是管理这些定时器,确保其在子线程创建且运行- // NIBP.h 文件
- class NIBPWorker : public QObject //一定要继承QObject
- {
- Q_OBJECT
- public:
- NIBPWorker();
- void InitTimer(); //创建所有定时器
- void StartWork(); //开启定时器
- void EndWork(); //停止定时器
- private:
- QTimer *mManualTimer; //所有测量定时器
- QTimer *mAutoTimer;
- QTimer *mSTATTimer;
- };
复制代码 使用细节:- // NIBP.cpp 文件
- //在NIBP类的构造函数中
- NIBPManager::NIBPManager()
- {
- mWorker = new NIBPWorker;
- mWorkerThread = new QThread;
- mWorker->moveToThread(mWorkerThread); //初始化后,立刻将worker类移到创建的子线程中
- connect(mWorkerThread, &QThread::started, mWorker, &NIBPWorker::InitTimer); //在移入子线程后,就可以用connect执行"worker"中定义的槽函数
- connect(this, &NIBPManager::SignalStartTest, mWorker, &NIBPWorker::StartWork);
- connect(this, &NIBPManager::SignalEndTest, mWorker, &NIBPWorker::EndWork);
- mWorkerThread->start(); //记得将子线程运行起来
- }
- void NIBPManager::StartNoramlTest() //这些信号可以在主线程,或者其他线程中发,不影响worker中槽函数的执行
- {
- emit SignalStartTest();
- }
- void NIBPManager::EndTest()
- {
- emit SignalEndTest();
- }
复制代码 以上,"Worker"类组合在NIBP类中,负责处理高频定时器的测量任务,且不会影响主线程UI。
3.注意事项和总结
1."Worker"类继承QObject的原因,是因为moveToThread函数为QObject类的函数。
2.在moveToThread之前,"Worker"类所有的方法在主进程内运行,无论是直接调用还是通过信号和槽调用。
3.moveToThread之后,"Worker"类通过信号和槽系统调用的方法,都在子线程内运行;但是直接调用带来的所有工作都在主进程内发生。
4.moveToThread之后,是否start对方法在哪个线程内调用没有影响。
5."Worker"类构造和析构函数永远都在主线程内调用。
参数博客
moveToThread后成员函数到底在哪里运行
QT中QThread的各个方法,UI线程关系,事件关系详解
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |