Qt多线程示例(一)

目录

1、数据生成器类(QDiceThread)

2、主程序调用类(Process)

3、mian.cpp程序启动

4、信号与槽机制测试


        数据生成器每隔500ms不断的生成新的数据,主线程进行处理和显示操作。main()函数中定义变量,启动线程,之后开启事件循环,等待进程结束。

        实现方式:主线程中使用Process类管理业务逻辑处理。在Process类中定义QDiceThread类实例对象threadA,threadA调用自身函数实现QDiceThread线程类的开启、关闭、暂停,QDiceThread线程类的run函数中不断产生新的数据,通过信号与槽机制,发送至Process类,Process类onthreadA_newValue槽函数接收到数据后显示。

1、数据生成器类(QDiceThread)

        其中,控制变量:m_Paused, m_stop控制run()函数中线程循环的暂停、结束。m_seq、m_diceValue为产生的数据,掷骰子次数及骰子点数,可在调用方直接访问也可通过emit信号当改变后直接发送给接收槽函数。

qdice_thread.h

#ifndef QDICE_THREAD_H
#define QDICE_THREAD_H

#include    

class QDiceThread : public QThread
{
    Q_OBJECT

public:
    QDiceThread();

    void    diceBegin();//掷一次骰子
    void    dicePause();//暂停
    void    stopThread(); //结束线程

private:
    int     m_seq=0;//掷骰子次数序号
    int     m_diceValue;//骰子点数
    bool    m_Paused=true; //掷一次骰子
    bool    m_stop=false; //停止线程

protected:
    void    run() Q_DECL_OVERRIDE;  //线程任务

signals:
    void    newValue(int seq,int diceValue); //产生新点数的信号
};

#endif // QDICE_THREAD_H

qdice_thread.cpp

#include qdice_thread.h
#include 
#include 
#include 

QDiceThread::QDiceThread():m_Paused(false)
{
}

void QDiceThread::diceBegin()
{
    //开始掷骰子
    m_Paused=false;
    qDebug()<<  "QDiceThread diceBegin(), tid : " << QThread::currentThreadId();
}

void QDiceThread::dicePause()
{
    //暂停掷骰子
    m_Paused=true;
}

void QDiceThread::stopThread()
{
    //停止线程
    m_stop=true;
    qDebug()<<  "QDiceThread stopThread(), tid : " << QThread::currentThreadId();
}

void QDiceThread::run()
{
     qDebug()<<  "QDiceThread run(), tid :"  << QThread::currentThreadId();

    //线程任务
    m_stop=false;//启动线程时令m_stop=false
    m_seq=0; //掷骰子次数
    qsrand(QTime::currentTime().msec());//随机数初始化,qsrand是线程安全的

    while(!m_stop)//循环主体
    {
        if (!m_Paused)
        {
            m_diceValue=qrand(); //获取随机数
            m_diceValue=(m_diceValue % 6)+1;
            m_seq++;
            qDebug() <<  "emit newValue:"  << m_seq << m_diceValue
                     << "tid : "<< QThread::currentThreadId();;
            emit newValue(m_seq, m_diceValue);  //发射信号
        }
        msleep(500); //线程休眠500ms
    }

//  在  m_stop==true时结束线程任务
    quit();//相当于  exit(0),退出线程的事件循环
}

2、主程序调用类(Process)

        实现对处理过程的封装。其中,控制变量:m_Paused, m_stop控制run()函数中线程循环的暂停、结束。m_seq、m_diceValue为产生的数据,掷骰子次数及骰子点数,可在调用方直接访问也可通过emit信号当改变后直接发送给接收槽函数。

process.h

#ifndef PROCESS_H
#define PROCESS_H

#include 
#include qdice_thread.h

class Process: public QObject
{
    Q_OBJECT

public:
    Process();
//    explicit Process(QObject *parent = nullptr);

private:
    QDiceThread threadA;

public:
    void startThread(); // 启动线程
    void stopThread(); // 停止线程

public slots:
    void onthreadA_started();
    void onthreadA_finished();
    void onthreadA_newValue(int seq, int diceValue);
};
#endif // PROCESS_H

process.cpp

#include process.h
#include 
#include 

Process::Process()
{
    connect(&threadA, SIGNAL(started()), this, SLOT(onthreadA_started()));
    connect(&threadA, SIGNAL(finished()), this, SLOT(onthreadA_finished()));
    connect(&threadA, SIGNAL(newValue(int,int)), this, SLOT(onthreadA_newValue(int,int)));
    qDebug()<<  Process Process(), tid : << QThread::currentThreadId();
}

//Process::Process(QObject *parent):QObject(parent)
//{
//    connect(&threadA, SIGNAL(started()), this, SLOT(onthreadA_started()));
//    connect(&threadA, SIGNAL(finished()), this, SLOT(onthreadA_finished()));
//    connect(&threadA, SIGNAL(newValue(int,int)), this, SLOT(onthreadA_newValue(int,int)));
//}

// 启动线程
void Process::startThread()
{
    qDebug()<< " Process startThread(), tid : "<< QThread::currentThreadId();
    threadA.moveToThread(&threadA);
    threadA.diceBegin(); // 控制变量,实现线程循环开始
    threadA.start(); // 线程开启,执行run()虚函数
}

// 停止线程
void Process::stopThread()
{
    qDebug()<<  " Process stopThread(), tid : "<< QThread::currentThreadId();
    if (threadA.isRunning())
    {
        threadA.stopThread(); // 控制变量,实现线程循环结束
        threadA.wait();// 等待线程结束
    }
}

void Process::onthreadA_started()
{
    qDebug()<<  "Process onthreadA_started(), tid : " << QThread::currentThreadId();
}

void Process::onthreadA_finished()
{
    qDebug()<<  "Process onthreadA_finished(), tid : " << QThread::currentThreadId();
}

void Process::onthreadA_newValue(int seq, int diceValue)
{
    qDebug()<<  "Process onthreadA_newValue(), tid : " << QThread::currentThreadId();
    qDebug() << "get value: seq=" << seq << ", diceValue=" << diceValue;
   // sleep(1);
    if (seq > 3)
    {
        stopThread();
    }
}

3、mian.cpp程序启动

        其中,控制变量:m_Paused, m_stop控制run()函数中线程循环的暂停、结束。m_seq、m_diceValue为产生的数据,掷骰子次数及骰子点数,可在调用方直接访问也可通过emit信号当改变后直接发送给接收槽函数。

#include 
#include qdice_thread.h
#include 
#include 
#include 
#include 
#include 
#include process.h
using namespace std;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug()<<  "mian(), tid : " << QThread::currentThreadId();
    Process proc;

    // 启动线程
    proc.startThread();
//    sleep(5);

//    // 结束线程
//    if (proc.m_recvCnt > 10)
//    {
//        proc.stopThread();
//    }

    return a.exec();
}

结果:

Qt多线程示例(一)_第1张图片

4、信号与槽机制测试

        示例代码中,线程1 run函数每隔500ms产生一次数据,通过信号与槽以消息队列机制将参数传递到Peocess中,Process类onthreadA_newValue槽函数接收到数据后显示。

        当onthreadA_newValue槽函数处理及时时,数据产生和数据显示线程同步,交替进行。但是存在问题:当槽函数处理不及时时,存在延迟(数据产生类并未等待数据处理完就又产生了新的数据),有时候会产生意想不到的效果。

测试代码:

void Process::onthreadA_newValue(int seq, int diceValue)
{
    qDebug()<<  Process onthreadA_newValue(), tid : << QThread::currentThreadId();
    qDebug() << get value: seq= << seq << , diceValue= << diceValue;
    sleep(1);

    if (seq > 3)
    {
        stopThread();
    }
}

测试效果:

Qt多线程示例(一)_第2张图片

         主线程中,设置投掷3次后结束数据生成线程,结果因为处理速度慢,当主线程接收到投掷次数为3时,实际上数据生成器类已经产生8次数据。这个显然是不合理的。

传送门qt多线程系列文章目录

你可能感兴趣的:(c++,qt)