1、令人不解的问题
当槽函数是线程类中的成员时,为什么依
然不在本线程内被调用执行?
隐藏的问题
-对象依附于哪一个线程?
-对象的依附性与槽函数执行的关系?
-对象的依附性是否可以改变?
对象依附于哪一个线程?
默认情况下,对象依附于自身被创建的线程;例 如:
对象在主线程(main()函数)中被创建,则依附于主线程。
int main(int argc, char *argv[])
{
//...
TestThread t; //依附于主线程
MyObject m; //依附于主线程
//...
}
对象的依附性与槽函数执行的关系?
默认情况下,槽函数在其所依附的线程中被调用执行!
int main(int argc, char *argv[])
{
//...
TestThread t; //依附于主线程
MyObject m; //依附于主线程
/*下面连接的槽函数都在主线程中被调用执行*/
QObject::connect(&t, SIGNAL(started()), &m, SLOT(getStarted()));
QObject::connect(&t, SIGNAL(testSignal()), &m, SLOT(testSlot()));
//...
}
对象的依附性是否可以改变?
QObject:: moveToThread用于改变对象的线
程依附性,使得对象的槽函数在依附的线程中
被调用执行。
int main(int argc, char *argv[])
{
//...
TestThread t; //依附于主线程
MyObject m; //依附于主线程
/*改变m的线程依附性,使其依附于线程t*/
m.moveToThread(&t);
//...
}
2、编程实验
对象的依附性 79-1.pro
TestThread.h
#ifndef TESTTHREAD_H
#define TESTTHREAD_H
#include <QThread>
class TestThread : public QThread
{
Q_OBJECT
protected:
void run();
public:
explicit TestThread(QObject *parent = 0);
signals:
void testSignal();
protected slots:
void testSlot();
};
#endif // TESTTHREAD_H
TestThread.cpp
#include "TestThread.h"
#include <QDebug>
TestThread::TestThread(QObject *parent) :
QThread(parent)
{
connect(this, SIGNAL(testSignal()), this, SLOT(testSlot()));
}
void TestThread::run()
{
qDebug() << "void TestThread::run() -- begin tid = " << currentThreadId();
for(int i=0; i<5; i++)
{
qDebug() << "void TestThread::run() i = " << i;
sleep(1);
}
emit testSignal();
qDebug() << "void TestThread::run() -- end";
}
void TestThread::testSlot()
{
qDebug() << "void TestThread::testSlot() tid = " << currentThreadId();
}
MyObject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);
signals:
protected slots:
void getStarted();
void testSlot();
};
#endif // MYOBJECT_H
MyObject.cpp
#include "MyObject.h"
#include <QThread>
#include <QDebug>
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
}
void MyObject::getStarted()
{
qDebug() << "void MyObject::getStarted() tid = " << QThread::currentThreadId();
}
void MyObject::testSlot()
{
qDebug() << "void MyObject::testSlot() tid = " << QThread::currentThreadId();
}
main.cpp
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QThread>
#include "TestThread.h"
#include "MyObject.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
qDebug() << "main() tid = " << QThread::currentThreadId();
TestThread t;
MyObject m;
QObject::connect(&t, SIGNAL(started()), &m, SLOT(getStarted()));
QObject::connect(&t, SIGNAL(testSignal()), &m, SLOT(testSlot()));
m.moveToThread(&t);
t.start();
return a.exec();
}
线程中的事件循环
-信号与槽的机制需要事件循环的支持
-QThread类中提供的exec()函数用于开启线程的事件循环
-只有事件循环开启,槽函数才能在信号发送后被调用
主线程开启了事件循环,所以槽函数能在主线程被调用
t 线程没有开启事件循环,所以槽函数不能在t线程调用
即要槽函数在指定的线程中调用,就需要在
指定的线程中调用exec()开启事件循环
小结论
-前提条件
对象依附的线程需要开启了事件循环
-后置结果
对象中的槽函数在依附的线程中被调用执行
3、编程实验
线程的事件循环 79-1.pro
在TestThread中开启t的事件循环
void TestThread::run()
{
qDebug() << "void TestThread::run() -- begin tid = " << currentThreadId();
for(int i=0; i<5; i++)
{
qDebug() << "void TestThread::run() i = " << i;
sleep(1);
}
emit testSignal();
exec(); //开启线程t的事件循环
qDebug() << "void TestThread::run() -- end";
}
那如果让t的槽函数也在自己的线程中被调用
只需在main函数中加入t.moveToThread(&t);
研究槽函数的具体执行线程有什么意义?
当信号的发送与对应槽函数的执行在不同线程中
时,可能产生临界资源的竞争问题!
例如:示例中的线程类中某个成员变量在本线程中改变,
但他的槽函数却在其它线程同时调用,同时修改这一变量
4、小结
默认情况下,对象依附于自身被创建的线程
QObject::moveToThread用于改变对象的线程依附性
信号与槽的机制需要事件循环的支持
exec()函数用于开启线程的事件循环
对象中的槽函数在依附的线程中被调用执行
5、To be continued
为什么exec后面的内容没有被执行?