一般在Qt中,我们有两种使用线程的方法:
- 声明一个类,该类继承QThread,我们只需重写run函数即可,在run函数中实现我们需要在线程中处理的事务。
- 声明一个类,该类继承QObject,假设该类实例化成a,调用a.moveToThread()该方法,即可将该对象移动到新线程中,此时对象中的槽函数归属于新线程,也就是信号接收者属于新线程,而且我们也推荐这样做
当然,这两种方法网上有一大堆的资料,这里就不在阐述了。而这里我们只探讨几个注意事项:
- 假设在方法1中实现的类为Thread,该类中实现了槽函数threadSlot:
-
//主线程中编写如下代码 Thread * thread = new Thread; //主线程中的信号test connect(this,SIGNAL(test()),thread,SLOT(threadSlot())); thread->start(); emit test();
此时该槽函数将会在主线程中执行,无论connect的第五个参数是什么,原因如下:
该线程由主线程创建,除了Thread中的run函数外,其余都属于主线程,
当调用Qt::DirectConnection时,槽函数由发射信号所在的线程执行——主线程
当调用Qt::QueuedConnection时,槽函数在由其所在线程再次进入事件循环的时候调用——主线程
Qt::AutoConnection,槽函数和发送信号同处一线程,相当于Qt::DirectConnection——主线程
Qt::QueuedConnection:信号发送者和接收者不能在同一线程,造成死锁。
要想让槽函数在其他线程中执行怎么做?那就在Thread的构造函数中添加一句
this->moveToThread(this);
然后在run中执行
exec();
解释:将对象移动到线程中(因为对象由主线程创建,归属主线程,需要移动),启动线程的事件循环——(不推荐这样做)
- 使用方法2时,不能绑定类的parent,否则会有如下警告 QObject::moveToThread: Cannot move objects with a parent,函数调用失败。
- QWidget不能调用方法2
- 方法2中的槽函数的执行必定是在调用目标线程的start()方法之后,所有一般执行完moveToThread方法后就调用线程的start方法,QThread的默认run方法如下,也就是线程进入了事件循环,开始处理消息:
void QThread::run() { (void) exec(); }