对象的线程依附性
每一个学过C++以及系统编程的程序员,对于变量会与特定线程有关联都会感到不可思议;在qt中所说的对象的线程依附性,只是针对继承自QObject的对象而言的;对象的线程依附性,并不是代表真的某个底层线程才能访问这个变量而其他线程不行;而是一种qt实现逻辑上的标记需要;这个qt实现逻辑就是qt核心机制信号槽机制;
qt对象的线程依附性的真正含义是:这个对象只接收或者只处理所依附线程的事件队列里面的事件【有人会问这跟信号槽有什么关系?请先记住这句话!】
在qt中每一个线程都可以有一个唯一的事件队列【类似于windows里面的消息队列】,线程事件队列中接受存放过来的事件任务,这个线程也进行事件循环从事件队列中取出事件任务分派给对应的对象去处理【类似于消息循环分派消息给对应的窗口处理,但是qt中这时分派给对象处理】;注意这里分派给继承自QObject的对象处理;对象所处理的事件任务,一定是从对象所依附的线程的事件队列中取出的任务!
我们现在已经讲了 线程事件队列,线程事件循环,对象的线程依附性;现在来看看connect也就是信号槽的真正语义是什么;
无论采用何种策略,connect的主体语义只有二种
1.同一线程内直接调用:这时信号的触发或者说调用信号线程与槽函数的触发执行是同一线程;【无论这个emit是手动显示调用还是预定义信号底层通过消息事件触发的】对应的emit的语义就是单线程内的直接调用
2.不同线程间的一个线程存放事件任务到另一个线程的事件队列中:这时信号的触发(调用信号)的线程就是存放动作的发出者,由这个线程存放事件任务到接收者所依附线程的事件队列中;所以这时候emit的语义就是事件任务存放到事件队列!
这里有几个需要注意说明的点:
1.信号触发线程,或者是信号调用线程指的是执行(调用)emit【无论是显示还是隐式】的线程,而非connect 发送者对象所依附的线程!
2.接收者依附线程确实指的是接收者对象所依附的线程
一般而言对象所依附的线程是创建这个对象时【即调用这个对象的构造函数】所在的线程!后面这个对象可以被moveToThread依附到其他线程,但是执行这个操作时需要注意,调用执行这个moveToThread的线程必须是此时这个对象所依附的线程【即依附线程本身才有权决定转让依附权给其他线程】
关于QThread对象的管理线程与所依附线程关系:
QThread对象的管理线程与所依附的线程不是一个线程;QThread对象管理的线程是一个新的底层线程,该线程被QThread对象管理【比如在QThread对象生命周期结束时,必须等待期管理的线程先结束】;
而QThread对象所依附的线程,是定义(创建)QThread对象的线程,可能是GUI线程也可能是其他线程;