在QThread中使用信号(SIGNAL)-槽(SLOT)
来源:互联网 发布:知其意思是什么 编辑:程序博客网 时间:2024/05/16 17:15
首先引用Bruce Eckel的一句话,“理解线程的概念,应该用面向过程编程的思路去理解,而不应该用面向对象编程的思路去理解”。
然后,上两段代码:
1、会发生槽调用的代码
//ThreadSlotTest.h#ifndef THREADSLOTTEST_H#define THREADSLOTTEST_H#include <QThread>#include <QTimer>#include <iostream>using namespace std;class ThreadSlotTest:public QThread{ Q_OBJECTprivate: QTimer timer;public: // ThreadSlotTest(){ moveToThread(this); timer.setInterval(1000); timer.start(); connect(&timer,SIGNAL(timeout()),this,SLOT(slot1())); } // void run(){ exec();//exec会让线程卡在这句话上,不会往下执行(除非调用exit或quit) }public slots: void slot1(){cout<<"slot1:"<<currentThreadId()<<endl;}};#endif // THREADSLOTTEST_H//main.cpp#include <QtGui/QApplication>#include <iostream>#include "ThreadSlotTest.h"using namespace std;int main(int argc, char *argv[]){ QApplication a(argc, argv); cout<<"main:"<<QThread::currentThreadId()<<endl; ThreadSlotTest tst; tst.start(); return a.exec();}
2、不发生槽调用的代码
//ThreadSlotTest.h#ifndef THREADSLOTTEST_H#define THREADSLOTTEST_H#include <QThread>#include <QTimer>#include <iostream>using namespace std;class ThreadSlotTest:public QThread{ Q_OBJECTprivate: QTimer timer;public: // ThreadSlotTest(){ moveToThread(this); timer.setInterval(1000); timer.start(); connect(&timer,SIGNAL(timeout()),this,SLOT(slot1())); } // void run(){ while(true);//只改了这一个地方哦~ }public slots: void slot1(){cout<<"slot1:"<<currentThreadId()<<endl;}};#endif // THREADSLOTTEST_H//main.cpp#include <QtGui/QApplication>#include <iostream>#include "ThreadSlotTest.h"using namespace std;int main(int argc, char *argv[]){ QApplication a(argc, argv); cout<<"main:"<<QThread::currentThreadId()<<endl; ThreadSlotTest tst; tst.start(); return a.exec();}
两段代码只差在ThreadSlotTest的run函数的实现上:
如果调用exec(),则会发生槽函数调用;
如果不调用exec(),则不发生槽函数调用。
看QThread的exec()的解释:
Enters the event loop and waits until exit() is called, returning the value that was passed to exit(). The value returned is 0 if exit() is called via quit().It is necessary to call this function to start event handling.
意思是:
exec()函数会让线程进入事件循环,直到exit()被调用,exec的返回值是调用exit时的实参值。如果通过quit,间接调用exit,以致exec退出,则exec返回0.如果想启用事件处理机制,就必须调用exec函数。
也就是说,之所以能发生槽调用,就是因为给本线程开启了事件处理机制。
真相原没这么简单!
如果你像我一样好奇,注意到了ThreadSlotTest的构造函数里的第一句话:
moveToThread(this);那么,恭喜你!你就快知道真相了!
如果把这句注释掉,则两段代码都会调用槽,而且显示的内容也都相同!
为什么?
1、为什么第二段代码里的槽函数不会被执行,而第一段代码里的会被执行?
moveToThread是QObject里的函数,其作用是将本对象事件处理变更到指定线程中执行,如果该线程没有开启事件处理机制,那么所有发给这个对象的信号都不会被相应的槽执行,而exec是开启事件处理机制的关键!
所以第二段代码不会执行槽,因为接受信号的对象(也就是含有需要被执行的那个槽的对象)被移动到ThreadSlotTest线程中,而该线程没有开启事件处理机制,也就是说,尽管timeout信号会发出(emit),但接收者所在的线程并不接收(因为事件处理机制没有开启),所以表现出来就是槽函数没有被调用。
第一段代码因为执行了exec,所以开启了事件处理机制,所以timeout信号的接收者所在的线程会接收并处理该信号,所以表现出来,就是槽函数被调用了。
2、为什么去掉moveToThread以后,两段代码都会被执行,而且输出的结果相同?
上面解释过moveToThread函数的作用。如果不执行moveToThread,那么ThreadSlotTest对象所在的线程就没有发生变化——该对象在执行main函数的线程中,那个线程的事件处理机制是由:
...QApplication a(argc, argv);...return a.exec();...开启的。
所以QTimer的timeout信号会发送给QApplication,然后又QApplication调用slot1槽函数,也就是说,槽函数的调用,跟ThreadSlotTest线程无关!所以ThreadSlotTest开或者不开事件处理机制,都无所谓了~
注意:如果你仔细观察的话,会发现,第一段代码在输出线程号的时候,main函数中输出的线程号与slot1函数中输出的线程号是不相同的!
为什么?因为使用了moveToThread!所以slot1的调用有ThreadSlotTest线程负责,因而与QApplication的线程号不相同!
去掉moveToThread以后,第一段和第二段代码中,输出的main函数中的线程号与slot1函数中输出的线程号是相同的,因为都是有QApplication发起的槽函数(slot1)调用!
没了~
参见:
1、QThread 的使用方法
2、QThread 使用探讨
两个都是大牛的文章!我们一起膜拜吧!
- 在QThread中使用信号(SIGNAL)-槽(SLOT)
- 如何在qt designer中自定义信号/槽(Signal/Slot)
- QThread 使用 slot 槽函数
- QThread 使用 SLOT 槽函数
- qt信号signal和槽slot机制
- signal-slot 信号槽技术初探一
- signal-slot 信号槽技术初探二
- qt信号signal和槽slot机制
- qt信号signal和槽slot机制
- 信号(SIGNAL)与槽(SLOT)
- qt信号signal和槽slot机制
- 信号和槽机制(Signal & Slot)
- qt信号signal和槽slot机制
- C++11 信号槽 signal/slot
- 在QGraphicsItem中使用signal和slot机制
- 在QGraphicsItem中使用signal和slot机制
- signal-slot 信号/槽(也译信号/插槽)机制
- 信号(Signal)与槽(Slot)-Qt中的典型机制
- 学习笔记
- shell每日更新(5)
- 只为更简单
- GNU Make 使用手册(中译版)
- 关于WSARECV与WSASEND,SOCKET_ERROR关闭997异常的问题
- 在QThread中使用信号(SIGNAL)-槽(SLOT)
- linux软中断的实现原理
- 问题记录
- 一站式C学习笔记
- css display:inline-block属性
- 第十七周实验报告(任务一)【二进制文件】
- 鸟哥的私房菜笔记(一)
- ACE6.0的安装_出错处理_检验
- 母爱温情画面:小蜗牛爬在妈妈壳上渡小水池