• 第七十九课、多线程中的信号与槽(中)------------------狄泰软件学院


    一、对象的依附性

    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
    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();
    }
    MyObject.cpp
    #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
    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";
     }
    TestThread.cpp

    线程对象依附性转移后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)、对象中的槽函数在依赖的线程中被调用执行

     

  • 相关阅读:
    双机调试环境部署
    VC++中通过MultiByteToWideChar将string|char*转换为wstring|wchar_t*
    Unicode环境下的类型转换
    SQL调优日记之发挥SQL性能与你的写法有关--对比三种方式实现相同功能
    从MS SQL删除大数据说开去
    Microsoft SQL Server Reporting Services (SSRS)报表技巧之在图表中增加参考线
    想个法子找出性能差的SQL
    MS SQL,数据库增长时众多表中谁是你关注的目标
    TSQL 日期处理总结
    投入.NET,我的第一篇BLOG
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6485965.html
Copyright © 2020-2023  润新知