对于自定义的信号和槽的触发,已经有示例测试过了。对于定时器消息,默认是在主线程中触发,那么如何在子线程中触发呢?本位以定时器为例,介绍一下对于系统消息,如何在子线程中触发。
工具/原料
qt
visual studio
准备工作
1、新建一个类,这个类继承QThread。定义一个QTimer定时器变量,以及对应的槽函数。在构造函数中绑定定时器,并启动定时器
2、同样在mainwindow中,也定义一个QTimer定时器变量,以及对应的槽函数。还定义了一个线程变量,在构造函数中绑定定时器,并启动定时器和线程
3、运行查看结果,两个定时器打印结果显示,都是在主线程中运行
在子线程启动定时器
1、修改代码,在run函数中启动定时器
2、在两个定时器函数中添加断点,调试。发现只有主线程的定时器函数触发,子线程并没有调到定时器的槽函数中
3、查看vs的输出窗口,只打印的主函数的定时器信息,还有一句“timers cannot be started from another thread”
4、搜索这个错误原因,描述如下:QObject是可重入的,它的大多数非GUI子类,例如QTimer,QTcpSo艘早祓胂cket,QUdpSocketandQProcess都是可重入的,使得这些类可以同时用于多线程。需要注意的是,这些类设计为从一个单一的线程创建和使用的,在一个线程创建对象,而从另外一个线程调用对象的函数并不能保证行得通。在本例中CMySignal的成员变量QTimer m_timer是在主线程创建CMySignal对象时创建的,但是是在CMySignal的run函数中调用,run函数运行在另一个线程中。所以提示错误。
在子线程中创建定时器
1、修改线程类,定义定时器指针的变量,在run函数中new定时器,绑定槽函数,然后启动定时器
2、查看运行结果,只有主线程的定时器函数打印了。子线程刚运行,就提示子线程退出
3、这是就需要在run函数中,增加一句exec函数了,用了启动子线程的消息循环
4、再次运行,发现子线程的定时器槽函数依旧是在主线程中触发这里信号槽连接使用的是默认连接,在多线旯皱镢涛程中则相当于QueuedConnection队列连接:内部通过postEvent实现的。不是搏皋咬夼实时调用的,槽函数永远在槽函数对象所在的线程中执行。这里槽函数对象所在线程就是主线程
5、新建一个类,用来处理定时器超时函数。在子线程中新建这个类的对象
6、再次查看运行结果,这时子线程的定时器在子线程中触发