第78课 - 多线程中的信号与槽(上)

版权声明:课程笔记内容整理于狄泰软件 https://blog.csdn.net/qq_39654127/article/details/81978300

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();
}

令人不解的问题 

           当槽函数是线程类中的成员时,为什么依

           然不在本线程内被调用执行? 

                                  更加深入分析

                     第79课 - 多线程中的信号与槽(中)

4、小结 

QThread类拥有发射信号定义槽函数的能力 

线程在进程内拥有一个唯一的ID值 

线程拥有独立的栈空间用于函数调用 

没有临界资源的函数可以无副作用的被多个线程调用 

槽函数的调用在某一个线程中完成 

 

猜你喜欢

转载自blog.csdn.net/qq_39654127/article/details/81978300