进程
多进程创建
在一个应用程序中启动另一个应用程序
/* 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);
}