Qt - 进程/线程

进程

多进程创建

在一个应用程序中启动另一个应用程序

/* widget.h */
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QProcess>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QProcess *my_process;
};
#endif // WIDGET_H

/* widget.cpp */

#include "widget.h"
#include "ui_widget.h"
//#include <QProcess>
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    my_process=new QProcess(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    // 启动另一个程序
    my_process->start("f:/Qt/6.2.4/mingw_64/bin/assistant.exe");
    // 阻塞主进程,只能运行my_process进程
    my_process->waitForFinished();

    // 进程之间的数据传输与共享 IPC 任务间的通信与同步
}

进程间通讯与同步 - 共享内存

/* widget.h */
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSharedMemory>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;

    QSharedMemory memShared; // 创建共享内存对象
};
#endif // WIDGET_H

/* widget.cpp */
#include "widget.h"
#include "ui_widget.h"

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

    /*
        键值:系统底层对该共享内存的唯一的标记
    */
    memShared.setKey("my_shared_mem");
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    // 判断该共享内存是否被绑定到其他的进程当中
    if(memShared.isAttached())
    {
        // 将该共享内存解除绑定
        memShared.detach();
    }

    // 创建一个共享内存
    // 设置该共享内存的读写模式
    if (!memShared.create(100,QSharedMemory::ReadWrite))
    {
        qDebug()<<"ERROR: create shared memory failed";
        return ;
    }

    // 共享资源的排他性,也就是加锁解锁机制

    // 对共享内存加锁,表示该共享内存只有该进程可以使用
    memShared.lock();

    // memShared 是共享内存类的对象,并不是该共享内存的地址
    // memShared.data() 才是该共享内存的地址,返回一个指针
    // 对于QByteArray 类对象,byteArray.data() 返回一个指向该字节组的一个指针
    QByteArray byteArray=ui->lineEdit->text().toLatin1();
    // qMin 取二者中的较少值
    memcpy(memShared.data(),byteArray.data(),(size_t)qMin(byteArray.size(),memShared.size()));

    // 对共享内存解锁
    memShared.unlock();


}

/* widget.h */
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSharedMemory>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QSharedMemory memShared;
};
#endif // WIDGET_H

/* widget.cpp */
#include "widget.h"
#include "ui_widget.h"

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

    // 用于进程之间通信的共享内存的键值必须是一样的
    memShared.setKey("my_shared_mem");
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    // 将该共享内存进行绑定
    // 要读取该共享内存中的数据,必须是已经绑定上的
    if (!memShared.attach())
    {
        qDebug()<<"ERROR: 绑定内存失败";
        return ;
    }

    // 加锁
    memShared.lock();

    // 读取共享内存
//    QByteArray byteArray;
    memcpy(byteArray.data(),memShared.data(),(size_t)qMin(byteArray.size(),memShared.size()));
//    memcpy(byteArray.data(),memShared.data(),(size_t)memShared.size());

//    qDebug()<<byteArray;
//    ui->label->setText(byteArray);

    // version2
    char *arr=new char[memShared.size()];
    memcpy(arr,memShared.data(),(size_t)memShared.size());
    ui->label->setText(QString(arr));

    // 解锁
    memShared.unlock();

}

线程

多线程就要自己从QThread派生一个类
所有的线程都是从类中的run函数开始的,一般所有的实现都是在run中实现
线程先start 然后start自动调用run函数

函数run一般是一个无限循环,可以在函数run里调用函数exit()或quit()结束线程的时效件循环,或是在主线程里调用函数terminat()强制结束线程

QThread继承自QObject,started信号在线程开始运行之前,也就是在函数run被调用之前被发射;finshed信号在线程即将结束时发射

多线程独立并发

自定义线程类

/* myThread.h */
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public:
    explicit MyThread(QObject *parent = nullptr);
    void threadStop();


signals:

protected:
    void run(); // 线程从run函数开始运行的, run函数的调用靠的是QThread类里的start函数,启动线程先调用start函数,然后start函数自动关联run函数

private:
    bool isStop;
};

class MyThreadSec:public QThread
{
    Q_OBJECT

public:
    explicit MyThreadSec(QObject *parent=nullptr);
    void threadStop();
signals:

protected:
    void run();

private:
    bool isStop;
};

#endif // MYTHREAD_H
/* myThread.cpp */

#include "mythread.h"
#include <QDebug>

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

void MyThread::run()
{
    int i=0;
    while (!isStop)
    {
        qDebug()<<"myThread i:"<<i;

        // 线程阻塞(延时)
        this->msleep(1000); // 以毫秒为单位
        i+=2;
    }
    if (isStop)
    {
        isStop=false;
    }
}

void MyThread::threadStop()
{
    isStop=true;
}

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

void MyThreadSec::run()
{
    int i=1;
    while (!isStop)
    {
        qDebug()<<"myThread i:"<<i;

        // 线程阻塞(延时)
        this->msleep(1000); // 以毫秒为单位
        i+=2;
    }
    if (isStop)
    {
        isStop=false;
    }
}

void MyThreadSec::threadStop()
{
    isStop=true;
}

widget类

/* widget.h */

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include "mythread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_4_clicked();

private:
    Ui::Widget *ui;
    MyThread *myThread;
    MyThreadSec *myThreadSec;
};
#endif // WIDGET_H
/* widget.cpp */

#include "widget.h"
#include "ui_widget.h"

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

    // 创建线程
    myThread=new MyThread(this);
    ui->pushButton_3->setEnabled(false); // 停止线程按钮默认不能被点击

    // 创建第二个线程
    myThreadSec=new MyThreadSec(this);
    ui->pushButton_4->setEnabled(false);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    // 启动线程,然后自动调用run函数
    myThread->start();
    ui->pushButton->setEnabled(false); // 启动线程按钮不能被点击
    ui->pushButton_3->setEnabled(true); // 停止线程按钮能被点击
}

void Widget::on_pushButton_3_clicked()
{
    // 判断线程是否正在运行
    if (myThread->isRunning())
    {
        // 设置停止标志
        myThread->threadStop();
        ui->pushButton->setEnabled(true);
        ui->pushButton_3->setEnabled(false);
    }
}


void Widget::on_pushButton_2_clicked()
{
    myThreadSec->start();
    ui->pushButton_2->setEnabled(false);
    ui->pushButton_4->setEnabled(true);
}



void Widget::on_pushButton_4_clicked()
{
    if (myThreadSec->isRunning())
    {
        myThreadSec->threadStop();
        ui->pushButton_2->setEnabled(true);
        ui->pushButton_4->setEnabled(false);
    }
}

信号量

自定义线程类

/* myThread.h */

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QObject>
#include <QThread>
#include <QSemaphore>

class Producer : public QThread
{
    Q_OBJECT
public:
    explicit Producer(QObject *parent = nullptr);
    void threadStop();
signals:

protected:
    void run();

private:
    bool isStop;
};

class Consumer:public QThread
{
    Q_OBJECT
public:
    explicit Consumer(QObject *parent=nullptr);
    void threadStop();

protected:
    void run();

private:
    bool isStop;
};

#endif // MYTHREAD_H

/* myThread.cpp */
#include "mythread.h"
#include <QDebug>

const int size=10;
unsigned int buffer[size];

QSemaphore usedSem(0); // 初始值为0 可以设置为0,取出内存空间中的数
QSemaphore nousedSem(size); // 初始值为10 表示内存空间中还没有多少个没有被填充,也就是内存空间为空(还有多少位置为空)

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

void Producer::run()
{
    static int procuder_i=0;
    while (!isStop)
    {
        qDebug()<<"producer waiting to produce...";
        // 获得信号量, 对应的信号量nousedSem 自动-1 ,是否大于=0 如果小于0则线程阻塞
        // 判断信号量是否>0 ,<=0则阻塞
        nousedSem.acquire();

        // 如果没有被阻塞,则继续执行,就向空的位置填充一个,表示生产一个
        buffer[procuder_i]=procuder_i;
        msleep(1000); // 每隔一秒钟生产一个
        qDebug()<<"wirte to shared buffer:"<<procuder_i;

        // 只要产生了一个,就可以有一个能被消费,则增加消费者信号量(初始为0)
        // 释放一个信号量, 对应的信号量usedSem 自动+1
        usedSem.release();

        procuder_i++;
        if (procuder_i==size) // 说明生产出来10个
        {
            procuder_i=0;
        }
    }

    isStop=false;
}

void Producer::threadStop()
{
    isStop=true;
}

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

void Consumer::run()
{
    static int consumer_i=0;
    while (!isStop)
    {
        // 获得信号量 自动-1,将要消费
        usedSem.acquire(); // 阻塞执行,消费者获得权限
        qDebug()<<buffer[consumer_i];

        nousedSem.release(); // 生产者获得权限(消费者消耗掉一个,生产者就可以多生产一个)

        consumer_i++;
        if (consumer_i==size)
        {
            consumer_i=0;
        }
    }

    isStop=false;
}

void Consumer::threadStop()
{
    isStop=true;
}

widget类

/* widget.h */

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QThread>
#include <QSemaphore> // 信号量头文件

#include "mythread.h"

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_3_clicked();

    void on_pushButton_4_clicked();

private:
    Ui::Widget *ui;
    Producer *producerThread; // 生产者线程
    Consumer *consumerThread; // 消费者线程
};
#endif // WIDGET_H

/* widget.cpp */

#include "widget.h"
#include "ui_widget.h"

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

    /*
        信号量:
            获得信号的 信号量>=0 线程可以运行;<= 线程只能阻塞

        实现两个信号量
            生产信号量 表示生产多少
            消费信号量 表示消耗多少
    */

    // 创建两个线程
    this->producerThread=new Producer(this);
    this->consumerThread=new Consumer(this);
    ui->pushButton_2->setEnabled(false);
    ui->pushButton_4->setEnabled(false);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    producerThread->start();
    ui->pushButton->setEnabled(false);
    ui->pushButton_2->setEnabled(true);
}


void Widget::on_pushButton_2_clicked()
{
    producerThread->threadStop();
    ui->pushButton->setEnabled(true);
    ui->pushButton_2->setEnabled(false);
}


void Widget::on_pushButton_3_clicked()
{
    consumerThread->start();
    ui->pushButton_3->setEnabled(false);
    ui->pushButton_4->setEnabled(true);
}


void Widget::on_pushButton_4_clicked()
{
    consumerThread->threadStop();
    ui->pushButton_3->setEnabled(true);
    ui->pushButton_4->setEnabled(false);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值