1、值得思考的问题
线程对象是否可以发射信号(signal) ?
是否可以定义槽函数(slot) ?
2、多线程中的信号与槽
QThread类拥有发射信号和定义槽函数的能力
-关键信号:
★ void started()
线程开始运行时发射该信号
★ void finished()
线程完成运行时发射该信号
★ void terminated()
线程被异常终止时发射该信号
让人逃避的问题
如果程序中有多个线程,槽函数是在哪个
线程中执行的?
概念小科普
-进程中存在栈空间的概念(区别于栈数据结构)
-栈空间专用于函数调用(保存函数参数,局部变量,等)
-线程拥有独立的栈空间(可调用其它函数)
小结论
只要函数体中没有访问临界资源的代码,同一个函数
可以被多个线程同时调用,且不会产生任何副作用!
实验前的准备
-操作系统通过整型标识管理进程和线程
★ 进程拥有全局唯一的ID值(PID)
★ 线程有进程内唯一的ID值(TID)
-QThread中的关键静态成员函数
★ QThread* currentThread ()
★ Qt::HANDLE currentThreadld ()
3、编程实验
线程类的信号与槽,槽函数的运行上下文 78-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();//线程ID
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();//槽函数被调用线程ID
}
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 getFinished();
void getTerminated();
};
#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::getFinished()
{
qDebug() << "void MyObject::getFinished() tid = " << QThread::currentThreadId();
}
void MyObject::getTerminated()
{
qDebug() << "void MyObject::getTerminated() 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(finished()), &m, SLOT(getFinished()));
QObject::connect(&t, SIGNAL(terminated()), &m, SLOT(getTerminated()));
t.start();
return a.exec();
}
令人不解的问题
当槽函数是线程类中的成员时,为什么依
然不在本线程内被调用执行?
更加深入分析
4、小结
QThread类拥有发射信号和定义槽函数的能力
线程在进程内拥有一个唯一的ID值
线程拥有独立的栈空间用于函数调用
没有临界资源的函数可以无副作用的被多个线程调用
槽函数的调用在某一个线程中完成