概述
众所周知,Qt
实现多线程的方式有两种,一种是通过子类化QObject
并将该类实例化后调用QObject::moveToThread
,将对象的所有函数执行放到另一个线程当中;另一种则是通过子类化QThread
后重写run
内的内容。当然,QtConcurrent::run
不算在此内。
在第一种
方法中,我们可以很容易得到槽函数
会在moveToThread
的那个线程中执行。再这,我们着重讨论第二种办法。
QThread
通常,我们对QThread
子类化后,会将需要执行的内容放在run
函数中。Qt
也告诉我们:**QThread
实例位于实例化它的旧线程中,而不是位于调用run()的新线程中。这意味着QThread
的所有队列槽函数和调用的方法都将在旧线程中执行。因此,希望在新线程中调用槽的开发人员必须使用worker对象方法;新的槽函数不应该直接实现到子类QThread中。**
1 | It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run(). |
那么有没有一种办法,让子类化QThread
的类实例中的槽函数在其内部执行呢?
connect
说起槽函数,就得说起connect
。这个函数在日常使用中通常只会注意前四个参数,但其第五个参数Qt::ConnectType
在当前应用场景中可以说有着独到之处。
下面的三个Qt::ConnectType
的值,有其独特的意义:
AutoConnection
:- 默认值;
- 如果信号在接收者所依附的线程发射,则为
DirectConnection
; - 如果发射信号的线程与接受者所依附的线程不同,则为
QueuedConnect
;
DirectConnection
:- 当信号发出时,槽函数直接被调用;
- 无论槽函数对象在哪个线程,函数调用都在信号发出者所依附线程执行;
QueuedConnection
:- 当控制权回到接受者所依附线程的事件循环时,槽函数被调用;
- 槽函数在接收者所依附线程执行;
moveToThread
说回QThread
,QThread
继承自QObject
。我们可以从此处下手,通过moveToThread(this)
,将子类化后的对象通过移到本线程执行。
此时通过信号调用槽函数时,槽函数会在当前QThread
子类依附线程执行。