Qt线程和signal-slot
Qt事件和信号的区别
问题:什么时候用事件,什么时候用信号呢?是不是不同的线程间用事件,信号不能用在线程间?
解答:
仔细来看,事件与信号其实并无多大差别,从我们对其需求上来说,都只要能注册事件或信号响应函数,在事件或信号产生时能够被通知到即可。但有一项区别在于,事件处理函数的返回值是有意义的,我们要根据这个返回值来确定是否还要继续事件的处理,比如在Qt中,事件处理函数如果返回true,则这个事件处理已完成,QApplication会接着处理下一个事件,而如果返回false,那么事件分派函数会继续向上寻找下一个可以处理该事件的注册方法。信号处理函数的返回值对信号分派器来说是无意义的。
另外还有一个需要我们关注的问题是事件和信号处理时的优先级问题。在Qt中,事件因为都是与窗口相关的,所以事件回调时都是从当前窗口开始,一级一级向上派发,直到有一个窗口返回true,截断了事件的处理为止。对于信号的处理则比较简单,默认是没有顺序的,如果需要明确的顺序,可以在信号注册时显示地指明槽的位置。
在Qt中,事件使用了一个事件队列来维护,如果事件的处理中又产生了新的事件,那么新的事件会加入到队列尾,直到当前事件处理完毕后,QApplication再去队列头取下一个事件来处理。而信号的处理方式有些不同,信号处理是立即回调的,也就是一个信号产生后,他上面所注册的所有槽 都会立即被回调。这样就会产生一个递归调用的问题,比如某个信号处理器中又产生了一个信号,会使得信号的处理像一棵树一样的展开。
评价:实际上信号-槽也可以异步的,这个bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoCompatConnection )
里面的Qt::AutoCompatConnection,可以根据实际情况确定。
一个问题:Qt里用线程,主线程是GUI,次线程是工作线程,如果次线程里也用消息循环(exec),即,主/次间用signal-slot通讯来实现同步,在这种情况下:
1. 主线程会被次线程block吗?
2. 如果在单cpu里会被block吗,如果次线程里不断循环,低层会自动分配时间片给主线程吗?
3. 这种方法和直接调用次线程中的方法,用mutex之类的来实现类似的循环,效率差别大吗?记得QT里讲过signal-slot只是多几个函数调用的差别。主次线程中怎样通讯比较有效?
QThread 现在默认状态下就是有一个消息循环的,而且鼓励使用线程独立的消息循环:
1.主线程会被次线程block吗?不会,QObject::connectd的最后一个参数(http://doc.qt.nokia.com/4.6/qt.html#ConnectionType-enum) 默认使用Qt::AutoConnection, 在多线程环境下,会自动选择Qt::QueuedConnection方式,除非强制使用Qt::BlockingQueuedConnection或者 Qt::DirectConnection, 否则线程不会block。
2. 如果在单cpu里会被block吗,如果次线程里不断循环,低层会自动分配时间片给主线程吗?线程和CPU个数没有关系,当然CPU多了,运行会更加流程,线程的资源分配(时间片)是由操作系统管理的,在各个系统上都是如此。
3. 这种方法和直接调用次线程中的方法,用mutex之类的来实现类似的循环,效率差别大吗? 执行效率上很难讲,但是mutex肯定是带来了开发效率的降低,你得小心翼翼地处理好各种临界资源的锁问题。
4. 记得QT里讲过signal-slot只是多几个函数调用的差别 是的,signal-slot的这种轻微的效率损失在绝大多数情况下不是问题,除非过度使用,这一般是设计上的错误导致的。