Qt两种线程方式的实现与优缺点对比(及信号槽连接方式)

Qt的线程实现主要两种方式:子类化QThread和对象moveToThread。

子类化QThread

实现方法:

  继承QThread

  重写run

  其它线程里使用start函数来启动此线程。

缺点

线程中的对象必须在run函数中创建。

线程无法接收信号,只能发送信号。

 

 对象moveToThread

实现方式:

新建类假设为Worker,在类的槽函数里实现逻辑,new一个QThread对象,并把Worker的实例化move到这个线程中去,连接好相应的信号和槽,在其它线程发射信号,此时槽函数会在线程里执行。

 

优缺点:

优点是克服了重写run的缺点,比较灵活简洁,但是不能在线程里面实现常驻任务(死循环的任务)。

 

轻量级的函数可以用movethread,无需创建独立线程类,例如你有多个小函数要在线程内做, 全部扔给一个QThread。还有一开始没使用线程,但是后边发觉这些代码还是放线程比较好,如果用子类化QThread的方法重新设计代码,将会有可能让你把这一段推到重来,这个时候,moveThread的好处就来了,你可以把这段代码的从属着movetothread,把代码移到槽函数,用信号触发它就行了。其它的话movetothread它的效果和子类化QThread的效果是一样的,槽就相当于你的run()函数,你往run()里塞什么代码,就可以往槽里塞什么代码,子类化QThread的线程只可以有一个入口就是run(),而movetothread就有很多触发的入口。

 

细节注意点:

moveToThread 只有槽函数才会在新线程里执行

该类new的时候不要指定父对象:否则移动失败,提示 QObject::moveToThread: Cannot move objects with a parent。

 

总结     

1、常驻任务使用继承QThread重写run     2、其他的一次性任务或者间歇性任务尽量都用moveToThread

 

 

信号槽连接方式

使用moveToThread的方式需要注意下信号槽的连接方式,主要注意前三种的特点。

第一种Qt::AutoConnection是系统默认的连接方式。这种方式连接的时候,槽不是马上被执行的,而是进入一个消息队列,待到何时执行就不是我们可以知道的了,当信号和槽不是同个线程,会使用第三种QT::QueueConnection的链接方式。如果信号和槽是同个线程,调用第二种Qt::DirectConnection链接方式

 

第二种Qt::DirectConnection是直接连接,也就是只要信号发出直接就到槽去执行,无论槽函数所属对象在哪个线程,槽函数都在发射信号的线程内执行,一旦使用这种连接,槽将会不在线程执行。

 

第三种Qt::QueuedConnection和第四种Qt::BlockingQueuedConnection是相似的,都是可以在不同进程之间进行连接的,不同的是,这里第三种是在对象的当前线程中执行,并且是按照队列顺序执行。当当前线程停止,就会等待下一次启动线程时再按队列顺序执行,等待QApplication::exec()或者线程的QThread::exec()才执行相应的槽,就是说:当控制权回到接受者所依附线程的事件循环时,槽函数被调用,而且槽函数在接收者所依附线程执行,使用这种连接,槽会在线程执行。如果没有在新的线程里,使用后,会放入消息队列里,等待exec。

 

第四种Qt::BlockingQueuedConnection是(必须信号和曹在不同线程中,否则直接产生死锁)这个是完全同步队列只有槽线程执行完才会返回,否则发送线程也会等待,相当于是不同的线程可以同步起来执行。

 

第五种Qt::UniqueConnection跟默认工作方式相同,只是不能重复连接相同的信号和槽;因为如果重复链接就会导致一个信号发出,对应槽函数就会执行多次。

 

第六种Qt::AutoCompatConnection是为了连接QT4 到QT3的信号槽机制兼容方式,工作方式跟Qt::AutoConnection一样。显然这里我们应该选择第三种方式,我们不希望子线程没结束主线程还要等,我们只是希望利用这个空闲时间去干别的事情,当子线程执行完了,只要发消息给主线程就行了,到时候主线程会去响应。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章