1. 进程 QProcess
1.1 知识点
在c语言中:
使用fork函数,由当前进程创建一个子进程,fork的子进程和父进程代码完全一致
在QT中:
QProcess类:额外执行新的程序,执行程序后就是一个新的进程执行
QProcess:进程管理类,使用QProcess类可以操作进程
start(程序的路径):启动进程
注意:
一个进程管理对象同时只能创建一个进程执行,当被管理的进程结束,可以启动下一个进程执行
1.2信号
绑定started() 信号,这个信号用来判断进程是否创建成功
绑定finished(int,QProcess::ExitStatus)信号,判断进程是否结束
绑定readyRead()信号,判断进程是否产生数据
1.3 举例
process
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QProcess>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
//启动是否成功的槽
void process_started();
//判断进程是否结束的槽
void process_finshed();
//判断进程是否产生数据的槽
void process_readyRead();
private:
Ui::MainWindow *ui;
QProcess* process;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
//进程的使用
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
//创建进程管理对象
process = new QProcess;
//绑定started() 信号,这个信号用来判断进程是否创建成功
connect(process,SIGNAL(started()),this,SLOT(process_started()));
//绑定finished(int,QProcess::ExitStatus)信号,判断进程是否结束
connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(process_finshed()));
//绑定readyRead()信号,判断进程是否产生数据
connect(process,SIGNAL(readyRead()),this,SLOT(process_readyRead()));
}
MainWindow::~MainWindow()
{
delete ui;
}
//启动一个新的进程
void MainWindow::on_pushButton_clicked()
{
//启动进程
//start()的参数要传一个路径,比如输入“notepad”,会打开一个新的记事本出来
//重点:一个进程管理对象只能创建一个进程,当被管理进程结束,就可以创建新的进程了
process->start(ui->lineEdit->text());
}
//是否启动成功
void MainWindow::process_started(){
qDebug()<<"进程启动成功";
ui->textEdit->append("创建成功");
}
//判断进程是否结束
void MainWindow::process_finshed(){
qDebug()<<"进程结束";
ui->textEdit->append("进程结束");
}
//判断进程是否产生数据,当有数据产生,就读取
void MainWindow::process_readyRead(){
//在进程产生数据时,读取该进程的数据
QByteArray data = process->readAll();
ui->textEdit->append(data);
}
2. 进程间通信 QSharedMemory
2.1 知识点
核心思想就是使用 QSharedMemory:共享内存
2.2 举例
发送端
process_write
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* shm;
};
#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);
//共享内存对象,并指定共内存id
shm = new QSharedMemory("hqyj");
//可以这样设置共内存id
// shm->setKey();
//创建并映射共享内存,1024是共享内存大小
shm->create(1024);
//单独映射也可以
// shm->attach();
}
Widget::~Widget()
{
delete ui;
}
//往共享内存中写
void Widget::on_pushButton_clicked()
{
//获取共享内存首地址
void* pdata = shm->data();
QString src = ui->textEdit->toPlainText();
//src.toStdString().c_str()
//src.toStdString()转换为c++标准字符串,c_str() 函将转换为指向以空字符(\0)结尾的 C 字符串
memcpy((char*)pdata,src.toStdString().c_str(),1024);
}
接收端
process_read
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* shm;
};
#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);
//创建共享内存对象
shm = new QSharedMemory;
//指定共享内存的id
shm->setKey("hqyj");
//映射共享内存
shm->attach();
}
Widget::~Widget()
{
delete ui;
}
//从共享内存中读
void Widget::on_pushButton_clicked()
{
//将共享内存拷贝到buf
char buf[1024];
memcpy(buf,shm->data(),1024);
ui->textEdit->setText(QString(buf));
}
3. 线程 QThread
3.1 知识点
核心思想就是,在创建一个类继承QThread,然后再新创建的类中重写run()函数执行线程,在主进程中 启动线程
线程:由进程中进行创建,在进程中额外执行一个新的任务就叫做线程。
在进程上下文切换时,系统开销比较大,多个线程在进程中,可以共享进程的资源,而调度方式和进程相同
在c语言中
pthread_create(&线程id,属性对象地址,线程起始函数,线程函数的参数);
在QT中
QThread:管理线程(线程开启、线程关闭、线程执行等)
run()函数:线程的执行(当线程执行时,就是执行run函数,QThread类已经由Qt完成,run不能修改----线程任务功能固定)
通过QThread类,派生出新类,派生类 也是线程类,同时重写 run函数实现需要的线程功能,当启动线程时,就执行自己的run作为线程任务
start():启动线程
3.2 信号
void finished():信号,线程结束
void started():信号,线程启动
3.3 举例
thread
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QDebug>
#include <thread1.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();
private:
Ui::Widget *ui;
//实例化线程对象
thread1* t1;
};
#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);
//创建线程对象
t1 = new thread1;
t1->str = "hello world";
}
Widget::~Widget()
{
delete ui;
}
//启动线程
void Widget::on_pushButton_clicked()
{
//启动
t1->start();
}
//改变线程打印的内容
void Widget::on_pushButton_3_clicked()
{
t1->str = ui->lineEdit->text();
}
//停止线程
void Widget::on_pushButton_2_clicked()
{
t1->stop();
}
thread1.h
#ifndef THREAD1_H
#define THREAD1_H
#include <QThread>
#include <QDebug>
class thread1 : public QThread
{
Q_OBJECT
public:
thread1();
//重写执行线程函数run()
void run();
void stop();
QString str;
bool ok;//循环标志位
};
#endif // THREAD1_H
thread1.cpp
#include "thread1.h"
thread1::thread1()
{
ok = true;
}
//执行线程
void thread1::run(){
while(ok){
qDebug()<<"thread1打印:"<<str;
sleep(1);
}
qDebug()<<ok;
}
//停止线程
void thread1::stop(){
ok=false;
}
4. 互斥锁
防止在多线程环境下,多个线程对一个变量同时修改
QMutex:互斥量
QReadWriteLock:读写锁
4.1 举例
还是上面的程序
thread
thread1.h
//互斥锁变量
QMutex* mutex;
thread1.cpp
//执行线程
void thread1::run(){
while(ok){
mutex->lock();//加锁
qDebug()<<"thread1打印:"<<str;
mutex->unlock();//解锁
sleep(1);
}
qDebug()<<ok;
}
widget.h
//互斥锁变量
QMutex* mutex;
widget.cpp
//改变线程打印的内容
void Widget::on_pushButton_3_clicked()
{
mutex->lock();//加锁
t1->str = ui->lineEdit->text();
mutex->unlock();//解锁
}
4.2读写锁
读写锁和互斥锁差不多,思想就是
1. 如果加了读锁,别的线程也可以加读锁,但是如果要去加写锁,就必须等待读锁的释放文章来源:https://www.toymoban.com/news/detail-811060.html
2. 如果加了写锁,别的线程要加锁就必须等待写锁的释放文章来源地址https://www.toymoban.com/news/detail-811060.html
到了这里,关于Qt进程和线程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!