一、对象的依附性
1、对象依附于哪个线程?
(1)、默认情况下,对象依附于自身被创建的线程(如对象在主线程main()函数)中被创建,则依附于主线程)
2、对象的依附性与槽函数执行的关系?
(1)、默认情况下,槽函数在对象所依附的线程中调用执行
3、对象的依附性是否可以改变?
(1)、QObject::moveToThread用于改变对象的线程依赖性,使得对象的槽函数在依附的线程中被调用执行
#ifndef MYOBJECT_H #define MYOBJECT_H #include <QObject> class MyObject : public QObject { Q_OBJECT public: explicit MyObject(QObject *parent = 0); signals: protected slots: void startslot(); void testSlot(); }; #endif // MYOBJECT_H
#include "MyObject.h" #include <QDebug> #include <QThread> MyObject::MyObject(QObject *parent) : QObject(parent) { } void MyObject::startslot() { qDebug() << "void MyObject::startslot()" << QThread::currentThreadId(); } void MyObject::testSlot() { qDebug() << "void MyObject::testSlot()" << QThread::currentThreadId(); }
#ifndef TESTTHREAD_H #define TESTTHREAD_H #include <QThread> class TestThread : public QThread { Q_OBJECT public: explicit TestThread(QObject *parent = 0); void run(); signals: void testsignal(); protected slots: void testslot(); }; #endif // TESTTHREAD_H
#include "TestThread.h" #include <QDebug> TestThread::TestThread(QObject *parent) : QThread(parent) { connect(this, SIGNAL(testsignal()), this, SLOT(testslot())); } void TestThread::testslot() { qDebug() << "void TestThread::testslot()" << QThread::currentThreadId(); } void TestThread::run() { qDebug() << "void TestThread::run()" << QThread::currentThreadId(); for(int i=0; i<5; i++) { qDebug() << "TestThread::run() i=" << i; sleep(1); } emit testsignal(); qDebug() << "void TestThread::run() end"; }
线程对象依附性转移后m的槽函数都不执行了
子线程的事件循环用来支持信号与槽的机制(让槽函数在线程中被调用)
二、线程中的事件循环
1、线程中的事件循环
(1)、信号与槽的机制需要事件循环的支持
(2)、QThread类中提供exec()函数用于开启线程事件循环
(3)、只有开启事件循环,槽函数才能在信号发送后被调用
2、线程的事件循环
(1)、信号发送后首先到事件队列
(2)、开启事件循环后就会到事件队列里面不断取信号
(3)、然后调用相应的槽函数
3、小结论
(1)、前提条件:对象依附的线程开启了事件循环
(2)、后置结果:对象中的槽函数在依附的线程中被调用执行
注意:在这里exec后面的语句不再执行
三、研究槽函数的具体执行线程的意义
1、当信号的发送与对应的槽函数不在同一线程时,可能发生临界资源的竞争问题
#include "TestThread.h" #include <QDebug> TestThread::TestThread(QObject *parent) : QThread(parent) { connect(this, SIGNAL(testsignal()), this, SLOT(testslot()));//1.如果testslot()槽函数在main中被调用 } void TestThread::testslot()//2.且在槽函数中访问TestThread的某个临界资源 { qDebug() << "void TestThread::testslot()" << QThread::currentThreadId(); } void TestThread::run()//3.run函数中也访问同一个临界资源,就会造成两个线程都访问临界资源 { qDebug() << "void TestThread::run()" << QThread::currentThreadId(); for(int i=0; i<5; i++) { qDebug() << "TestThread::run() i=" << i; sleep(1); } emit testsignal(); exec(); qDebug() << "void TestThread::run() end"; }
四、小结
(1)、默认情况下,对象依附于自身被创建的线程
(2)、QObject::moToThread()用于改变对象的线程依赖性
(3)、信号与槽的机制需要事件循环的支持
(4)、exec()函数用于开启线程的事件循环
(5)、对象中的槽函数在依赖的线程中被调用执行