美文网首页
多线程的两种实现方式

多线程的两种实现方式

作者: xqiiitan | 来源:发表于2025-05-07 14:32 被阅读0次

多线程
1>.Qt 4.7 之前的线程使用方法 -- 简单
a.继承QThread类,自己实现一个子类a;
b.重写子线程类中的虚函数 run()[线程的入口国数];
c.需要时使用start 函数启动子线程,进入run函数;
d.使用信号和槽完成和 主线程之间的通信.
signals: sigDone();
emit sigDone();

2.Qt4.7之后的线程使用方法 -- 灵活
3.使用后者的一些注意事项
4.conmect函数最后一个参数的作用
a.默认连接
b.队列连接
c.直接连接

数据库操作
1>. QSqlDataBase
2>.QSqlQucry
3>.QSqlTablcModel
1.创建对象
2.设置数据库表
3.将nodel放Avlew(QTableview)中
4.显示(查询)数据
5.设盟表头:setHeaderDate()
6. setEditgtratesy()

1.多线程。

// ui页面,右击按钮,转到槽。不要connect直接给按钮begin 关联click事件。on_begin_clicked().

#include <QTimer>
QTimer * myTimer;
#include <QThread>
#include <QDebug>
MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    myTimer = new Timer(this); // 初始化
    connect(myTimer, &QTimer::timeout, this,[=](){
        static int num=0;
        ui->lcdNumber->display(num++);
    });
}   

void MyWidget::on_begin_clicked() 
{
    if(myTimer->isActive() == true) {
        return;
    }
    myTimer->start(500); // 启动定时器,单位ms
    // 模拟复杂的操作。
    QThread::sleep(5); //休眠,单位秒
    myTimer->stop();
    qDebug() << "timer is stop..."; 
}

// 处理子线程信号
connect(myt, &MyThread::sigDone, mytimer, &QTimer::stop);

老的实现方法

//mythread.h  MyThread类。
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = 0);
    
protected:
    void run(); // 入口函数 -- 需要start()启动
signals:
    void sigDone();

public slots:
};
#endif // MYTHREAD_H
//mythread.cpp
#include "mythread.cpp.h"
MyThread::MyThread(QObject *parent) : QThread(parent)
{
}
void MyThread::run() // 重写虚函数
{
    // 复杂的操作
   // sleep(5);
    for(int i=0; i<100000000; ++i)
    {
        for(int j=0;j<10000000; ++j)
        {

        }
    }
    emit sigDone(); // 执行完,发送信号出去。
}

//mywidget.h

#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QTimer>
#include "mythread.h"

namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();
private slots:
    void on_begin_clicked();

private:
    Ui::MyWidget *ui;
    QTimer* mytimer; //定时器
    MyThread *myt;   //子线程
};
#endif // MYWIDGET_H

//mywidget.cpp

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QThread>
#include <QDebug>

MyWidget::MyWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::MyWidget)
{
    ui->setupUi(this);
    mytimer = new QTimer(this);//实例化定时器
    myt = new MyThread(this);  //实例化线程

    connect(mytimer, &QTimer::timeout, this, [=]()
    {
        static int num = 0;
        ui->lcdNumber->display(num++);
    });

    // 子线程信号,关联。收到子线程信号,mytimer 关闭QTimer。
    connect(myt, &MyThread::sigDone, mytimer, &QTimer::stop);
}
MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::on_begin_clicked() // ui界面有begin按钮。
{
    if(mytimer->isActive() == true)
    {
        return;
    }
    // 启动定时器
    mytimer->start(500); // ms
    // 启动线程,调用start方法,去启动run方法。
    myt->start();
}

新的实现方法

页面有开始,停止按钮,一个lcd显示器。
//mywidget.h .cpp

#ifndef MYWIDGET_H
#define MYWIDGET_H
#include <QWidget>
#include <QTimer>
#include "mywork.h"
#include <QThread>

namespace Ui {
class MyWidget;
}
class MyWidget : public QWidget
{
    Q_OBJECT

public:
    explicit MyWidget(QWidget *parent = 0);
    ~MyWidget();

    // 开始按钮,关联的槽函数。
    void slotStart();
    // 关闭按钮
    void slotStop();
    // 定时器
    void slotTimeout();
    // 关闭线程
    void slotCloseThread();

signals:
    void sigWorking();
private:
    Ui::MyWidget *ui;
    QTimer* mytimer;
    MyWork *work;
    QThread* pthread;
};
#endif // MYWIDGET_H
#include "mywidget.h"
#include "ui_mywidget.h"
#include <QDebug>


MyWidget::MyWidget(QWidget *parent) : QWidget(parent)
  ,ui(new Ui::MyWidget)
{
    ui->setupUi(this);

    /* 多线程使用注意事项:
     * 1. 业务对象, 构造的时候不能指定父对象
     * 2. 子线程中不能处理ui窗口(ui相关的类)
     * 3. 子线程中只能处理一些数据相关的操作, 不能涉及窗口
    */
    mytimer  = new QTimer(this);
    // 1. 业务对象
    work = new MyWork();
    // 2. 子线程类
    pthread = new QThread(this);
    // 3. 移动业务对象到子线程
    work->moveToThread(pthread);
    // 5. 子线程工作
    connect(this, &MyWidget::sigWorking, work, &MyWork::doMyWork);
    
    // 启动,关闭按钮关联槽函数
    connect(ui->start, &QPushButton::clicked, this, &MyWidget::slotStart);
    connect(ui->stop, &QPushButton::clicked, this, &MyWidget::slotStop);
    // 定时器
    connect(mytimer, &QTimer::timeout, this, &MyWidget::slotTimeout);

    // 窗口析构的时候干掉线程
    connect(this, &MyWidget::destroyed, this, &MyWidget::slotCloseThread);
    qDebug() << QThread::currentThread() << "main thread";
    /* connect 的第 5 参数
     * 1. 自动连接 -- 默认
     *      多线程 -- 指定队列连接
     *      单线程 -- 指定直接连接
     * 2. 队列连接 -- 多线程
     *      槽函数在信号接受者(receiver)所在的线程中执行
     * 3. 直接连接 -- 单线程
     *      信号和槽函数在同一个线程中执行
    */
}
MyWidget::~MyWidget()
{
    delete ui;
}

void MyWidget::slotStart() //启动槽函数
{
    if(mytimer->isActive() == true)
    {
        return;
    }
    if(pthread->isRunning())
    {
        return;
    }
    mytimer->start(500);
    // 4. 启动子线程
    pthread->start();
    // 发信号, 让子线程工作
    emit sigWorking();
}

void MyWidget::slotStop()
{
}

void MyWidget::slotTimeout()
{
    static int num = 0;
    ui->lcdNumber->display(num++);
}

void MyWidget::slotCloseThread()
{
    work->setFlage(true);
    pthread->quit();
    pthread->wait();    // 等待线程手头上的工作处理完成
}

mywork.h .cpp

#ifndef MYWORK_H
#define MYWORK_H
#include <QObject>
class MyWork : public QObject
{
    Q_OBJECT
public:
    explicit MyWork(QObject *parent = 0);

    // 业务处理函数
    void doMyWork();
    void setFlage(bool bl);

signals:
    void sigDone();

public slots:
private:
    bool isStop;
};
#endif // MYWORK_H
#include "mywork.h"
#include <QThread>
#include <QMessageBox>
#include <QDebug>

MyWork::MyWork(QObject *parent) : QObject(parent)
{
    isStop = false;
}

void MyWork::doMyWork()
{
    while(!isStop)
    {
        // 操作
        QThread::sleep(1);  // 当前线程处理操作用了1s
        // 每执行一次循环发一次信号
        emit sigDone();
        qDebug() << QThread::currentThread() << "sub thread";
        // QMessageBox::aboutQt(NULL);
        if(isStop)
        {
            break;
        }
    }
}

void MyWork::setFlage(bool bl)
{
    isStop = bl;
}

相关文章

网友评论

      本文标题:多线程的两种实现方式

      本文链接:https://www.haomeiwen.com/subject/fkerijtx.html