栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

qt中Qthread线程的使用以及安全关闭

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

qt中Qthread线程的使用以及安全关闭

前言

以前第一次使用线程的时候总是无法实现自己想要的效果,且为解决线程安全关闭的问题,今天看到一位老师讲了关于线程的使用方法,理解虽然还不是特别深刻,但已初步总结出相关注意事项。


环境:

  • qt5.12.12
  • windows操作系统

使用线程思路:

  1. 新建线程类,继承QThread
  2. 重写run()方法,将复杂程序都写在run的实现中,并设置循环条件(记得有些资料说线程必须写循环)
  3. 通过start()方法开启线程,通过requestInterruption()方法发出中断请求来跳出循环条件,跳出循环后该线程结束
  4. 在线程类中设置信号槽,当线程结束时杀死线程
  5. 在线程的析构函数中也要添加requestInterruption()中断请求,防止强制关闭窗口时线程不能安全关闭

先列举重要代码:(记得类要继承QThread)

AudioThread.h文件

void run() override;

AudioThread.cpp文件

//构造函数
AudioThread::AudioThread(QObject *parent) : QThread(parent)
{
    // 当监听到线程结束时(finished),就调用deleteLater回收内存
    connect(this,&AudioThread::finished,this,[=](){
        this->deleteLater();
        qDebug()<<"线程结束";
    });
}

//析构函数
AudioThread::~AudioThread()
{
    //强制关闭窗口时,线程也能安全关闭
    requestInterruption();
    wait();
    qDebug()<<"析构函数";
}

void AudioThread::run()
{
	.....自定义代码
    while(!isInterruptionRequested()){//当没发出中断请求时,执行循环体
        .....自定义代码
    }
    .....自定义代码
}

开启线程:

	AudioThread *audio_thread=new AudioThread(this);
    audio_thread->start();

关闭线程:

    audio_thread->requestInterruption();
    audio_thread->wait();	//等待线程结束才能执行下面代码
    audio_thread=nullptr;

完整代码:(我这里是通过线程调用ffmpeg实现音频录制,看起来会有点复杂,可只关注重要代码,也不要盲目复制粘贴,运行之前需要先配置ffmpeg)

AudioThread.h文件

#ifndef AUDIOTHREAD_H
#define AUDIOTHREAD_H

#include 
#include 

class AudioThread : public QThread
{
    Q_OBJECT
public:
    explicit AudioThread(QObject *parent = nullptr);
    ~AudioThread();

private:
    void run() override;
signals:

};

#endif // AUDIOTHREAD_H

AudioThread.cpp文件

#include "audiothread.h"

#include 
#include 

extern "C"{
// 设备相关API
#include 
// 格式相关API
#include 
// 工具相关API(比如错误处理)
#include 
// 编码相关API
#include 
}


#ifdef Q_OS_WIN
    // PCM文件的文件名
    #define FILENAME "E:/media/out.pcm"
#else
    #define FILENAME "/Users/mj/Desktop/out.pcm"
#endif

AudioThread::AudioThread(QObject *parent) : QThread(parent)
{
    // 当监听到线程结束时(finished),就调用deleteLater回收内存
    connect(this,&AudioThread::finished,this,[=](){
        this->deleteLater();
        qDebug()<<"线程结束";
    });
}

AudioThread::~AudioThread()
{
    //强制关闭窗口时,线程也能安全关闭
    requestInterruption();
    wait();
    qDebug()<<"析构函数";
}

void AudioThread::run()
{

    char *FMT_NAME="dshow";
    const AVInputFormat *localAv_find_input_format = av_find_input_format(FMT_NAME);
    if(!localAv_find_input_format){
        qDebug()<<"找不到输入格式"<
        char errbuf[1024];
        av_strerror(ret,errbuf,sizeof(errbuf));
        qDebug()<<"打开设备失败"<
        qDebug()<<"文件打开失败"<
        //采集数据
        ret = av_read_frame(ctx,pkt);

        if(ret==0){
            //向文件中写
            file.write((char *)pkt->data,pkt->size);
            qDebug()<<"正在录制,文件正在写入";

            //释放资源
            av_packet_unref(pkt);
        }else if (ret == AVERROR(EAGAIN)) { // 资源临时不可用
            continue;
        }
        else{
            char errbuf[1024];
            av_strerror(ret,errbuf,sizeof(errbuf));
            qDebug()<<"av_read_frame出错"< 

主线程调用子线程:

void MainWindow::on_pushButton_clicked()
{

    if(!is_record){
        audio_thread=new AudioThread(this);//这里我在主文件中进行了声明AudioThread *audio_thread=nullptr;
        audio_thread->start();
        qDebug()<<"开始录制";
        ui->pushButton->setText("结束录制");
        is_record=true;
    }else{
        audio_thread->requestInterruption();
        audio_thread->wait();
        audio_thread=nullptr;//及时置空防止出现野指针
        qDebug()<<"结束录制";
        ui->pushButton->setText("开始录制");
        is_record=false;
    }
}

程序效果:

感觉QThread使用起来注意事项还是比较多的,后续有新的理解会继续补充


码字不易,如果这篇博客对你有帮助,麻烦点赞收藏,非常感谢!有不对的地方

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/973370.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号