Qt的信号槽有五种连接方式定义在enum Qt::ConnectionType,下面简单介绍
Qt::AutoConnection:自动判断连接方式,如果信号发送对象和执行槽对象在同一线程,那么等于Qt::DirectConnection,如果不是则等于Qt::QueuedConnection
Qt::DirectConnection:直接连接方式,简单说就是直接调用,信号发送会在槽函数执行完毕后返回,但前提是信号和槽的对象必须在同一线程中,否则会出现未知错误
Qt::QueuedConnection:队列连接方式,信号的发送是通知当前线程事件机制增加一个待处理事件,槽的执行不一定能马上返回,发送信号马上返回,两者是异步执行,主要是为了解决信号和槽对象不在同一线程不阻塞的情况
Qt::BlockingQueuedConnection:阻塞队列连接方式,逻辑基本和前者相同,唯一的区别是,发送信号不会马上返回,一定会等到槽执行完毕返回后,才返回信号调用,对于需要阻塞等到返回值结果的时候,可以使用
Qt::UniqueConnection:独立连接方式,这个标识比较少用,可以和上面4个标识做OR运算表示这个连接对象为单例,如果有一样的对象信号绑定了一样的槽,绑定动作会返回失败
单线程的情况没什么好说,第二种方式直接的调用,主要说一下多线程的情况
写UI的同学应该都有使用过以下回调函数,这是因为在qt里子线程不能操作UI相关的对象接口,必须要把事件和动作交给主线程处理
那么一般就会有两种情况,阻塞和非阻塞式;阻塞式就是必须要等到这次动作的返回值才能往下执行,如果以第三种连接方式,即使加上了QGenericReturnArgument也无效,就需要选择第四种连接方式
但是Qt::BlockingQueuedConnection在子线程不受你控制或者不在你自己的代码里的时候,容易发生死锁,比如一个主线程调用子线程的某方法,在这个方法里又发送了信号交给主线程处理事件,由于子线程一直等待主线程处理完事件返回继续往下,但主线程又卡在了调用子线程方法的地方,导致二者直接死锁,所以这个连接方式要慎用,至少你要明白引发这种连接信号一系列的调用关系再来确认怎么处理;另外还有一种情况需要block,那就是参数中有指针的情况,如果这个指针的指向对象是临时变量,当非阻塞方式交出去的时候,可能对象已经析构回收掉了,那么调用参数会访问一个野指针,所以要么拷贝一份指针数据到可靠的地方(至少确认执行的时候数据还在),要么就得用阻塞方式,等待处理结束后,再释放指针指向对象。
Demo代码待续,主要会列举一下几种方式的正常调用写法