
常见的信号槽的绑定如下QObject::connect(sender,Sender::SignalFunc,receiver,Receiver::SlotFunc,Qt::AutoConnection); //Qt::AutoConnection 为默认选项关于槽函数最终是在哪个线程执行的引用一段说明https://www.cnblogs.com/findumars/p/5031239.html1、自动连接(Auto Connection)这是默认设置如果信号在接收者所依附的线程内发射则等同于直接连接如果发射信号的线程和接受者所依附的线程不同则等同于队列连接也就是这说只存在下面两种情况2、直接连接(Direct Connection)当信号发射时槽函数将直接被调用。无论槽函数所属对象在哪个线程槽函数都在发射信号的线程内执行。3、队列连接(Queued Connection)当控制权回到接受者所依附的线程时槽函数按照位于队列中的先后顺序被依次调用。槽函数在接收者所依附线程执行。其中接受者所依附的线程指的是接受者被创建的那个线程。每个QObject都有一个指向线程信息的指针可据此判定其属于哪个线程。由于QObject对象支持将自身移动到新线程的功能所以接受者依附的线程也不总是创建它的那个线程而这又导致了QThread的两种截然不同的使用方法1. 如果接受者被moveToThread移到新的线程中则接受者所依附的线程就变成那个新的线程了Receiver* receiver new Receiver; QThread* new_thread_manager new QThread; receiver-moveToThread(new_thread_manager);需要注意新的线程不是指new_thread_manager 这个对象这个new_thread_manager 对象本身依附于创建它的线程它主要是提供一些接口来管理这个新线程。新线程内部会开启一个事件循环监听依附该线程的对象是否有事件发生(socket事件/定时器事件/ui消息/信号emit等linux使用epoll/windows使用隐藏窗口消息)并监测new_thread_manager某些标志位是否变化(比如线程退出控制标志等)一旦检测到事件就绪就执行该事件的回调函数(也就是槽函数)。如果某个回调执行很耗时整个事件循环就会被阻塞住现象就是其他的信号无法得到及时响应。因此除非新线程只处理这一件事否则receiver的槽函数里面就不要写死循环了死循环将导致它所依附线程的事件循环失效。2. 如果是SubThread继承QThread则需要重载run函数(run函数会在新线程内部执行)。重载run函数也有两种做法①. 在重载的run函数里面自己写一个死循环取代事件循环(不要需要执行exec了意味着原事件循环失效)直接在新线程里面处理耗时事务通过标志位控制退出。②. 直接调用exec()开启QThread自带的事件循环。(实际上没重载之前父类QThread的run函数里面就是这样做的)ps: 不论方法①还是方法②只要信号的接收者是SubThread对象不论信号从何处发出槽函数都只在SubThread对象依附的线程内执行(通常这些槽函数会修改SubThread线程管理对象的某些标志位从而控制新线程的执行或终止只不过对于方法①而言这些标志位即便被修改了也不一定能达到控制线程的目的主要还是要看死循环内部的控制逻辑)。综上所述由于耗时事务会导致事件循环阻塞所以如果想用新线程处理耗时事务应该直接放弃事件循环选择方法2.①自行定义新线程内部循环逻辑。QT要求父子对象必须在同一个线程如果创建QObject 时给了一个不属于当前线程的父对象指针则父子关系构建会失败默认新建对象为孤儿对象相当于parent 指针为nullptr 。在movetothread 时如果存在父对象则move 操作会静默失败对象依旧在原线程。如果没有父对象将会连同所有子对象一起迁移至新线程。