C++回调函数与多线程联动使用

这篇具有很好参考价值的文章主要介绍了C++回调函数与多线程联动使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

问题

在业务场景中,会遇到这样的情况,当前类需要运行一个函数,这个函数会被使用多次或者耗时非常长,这时候我们希望把它放到子线程里面运行,主线程只需要知道它的运行状态即可(类似于进度条通知)。但我们又不希望更改该类任何地方(该类有可能是同事提供的,原则上只加不改最好)。

具体设置

首先我们创建一个常规类MainWindow,里面具有我们需要使用的方法,这里图简单,直接创建一个QT window工程。

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void test(QString* s);
    QString* s = new QString("sss");
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

MainWindow.cpp

#include "qdebug.h"
#include <iostream>
#include <functional>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    s = new QString("sss");
     qDebug()<<"变化前"<<*s;
    test(s);
     qDebug()<<"变化后"<<*s;
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::test(QString* s)
{
    qDebug()<<"test::run"<<QThread::currentThreadId();
    qDebug()<<"test::run"<<*s;
    *s += "qqq";
}

简单测试,运行结果:

MyThread::run 0x324c
变化前 "sss"
test::run 0x324c
test::run "sss"
变化后 "sssqqq"

现在我们希望使用子线程回调函数来调用我们的test函数,也就是把它移到子线程中运行,为了使代码减少耦合度,我们不在本类中修改。创建一个线程类ThreadTask。
其中包含预设的回调函数定义。
ThreadTask.h

//普通回调 普通回调需要保证调用的函数需要为static或者本类能够实际找到的地址。
typedef void (*mCallback)(QString* s); // 回调
//这里有一个重点,如果你是不同类之间调用回调的话,需要添加类名声明。
typedef void (MainWindow::*mCallback)(QString* s); // 回调
#ifndef THREADTASK_H
#define THREADTASK_H

#include <qthread.h>
#include <qdebug.h>
#include "mainwindow.h"


typedef void (MainWindow::*mCallback)(QString* s); // 回调
class ThreadTask :public QThread
{
    Q_OBJECT
public:
    //回调对象
    MainWindow *_obj;
    enum STATUS{
        running,
        waiting,
    };
    //回调函数参数
    //参数存储
    QString* s;
    //线程状态
    STATUS status = waiting;
    //回调函数存储
    mCallback callback_function;
    //构造
    ThreadTask();
    //设置回调函数
    void set_callback(MainWindow* obj,mCallback callback, QString * str);
protected:
    void run();//多线程执行的内容将通过重新该虚函数实现
signals:
    void over();
};

#endif // THREADTASK_H

ThreadTask.cpp

#include "threadtask.h"
#include "qdebug.h"
ThreadTask::ThreadTask()
{
}
void ThreadTask::set_callback(MainWindow* obj, mCallback callback,QString* str)
{
    s = str;
    qDebug()<<"set_callback"<<*s;
    _obj = obj;
    callback_function =callback;
}
void ThreadTask::run()
{
    status =running;
    qDebug()<<"ThreadTask::run"<<QThread::currentThreadId();
    (_obj->*callback_function)(s);
    emit over();
    status =waiting;
}

编写完子线程回调后,我们修改一下最初的函数调用形式。

#include "qdebug.h"
#include "Public_Define.h"
#include <iostream>
#include <functional>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ThreadTask * thread =new ThreadTask();
    connect(thread,&ThreadTask::over,this,[=](){
        qDebug()<<"变化后"<<*s;
    });
    qDebug()<<"MyThread::run"<<QThread::currentThreadId();



    qDebug()<<"变化前"<<*s;
    mCallback call(&test);
    thread->set_callback(this,call,s);
    thread->start();
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::test(QString* s)
{
    qDebug()<<"test::run"<<QThread::currentThreadId();
    qDebug()<<"test::run"<<*s;
    *s += "qqq";
}

可以发现我们并没有修改到原类的大部分内容,只修改了test函数的调用方式。看看运行效果。

MyThread::run 0x6d24
变化前 "sss"
set_callback "sss"
ThreadTask::run 0x52a0
test::run 0x52a0
test::run "sss"
变化后 "sssqqq"

可以看到我们把test任务成功以回调的形式在子线程中运行。

总结

通过创建一个子线程类并附加回调定义,我们很轻松地实现了在任意一个类中对特定方法进行异步调用(多线程调用),从而达到提高运行效率、防卡顿异步处理等效果。
后续希望能够将子线程类作为一个模板类,提高它的健壮性,让其能够作为一个通用方法使用。文章来源地址https://www.toymoban.com/news/detail-689022.html

到了这里,关于C++回调函数与多线程联动使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++11并发与多线程笔记(10) future其他成员函数、shared_future、atomic

    status = result.wait_for(std::chrono::seconds(几秒)); 卡住当前流程,等待std::async()的异步任务运 行一段时间,然后返回其状态std::future_status 。如果std::async()的参数是std::launch::deferred(延迟执行),则不会卡住主流程。 std::future_status是枚举类型,表示异步任务的执行状态。类型的取值

    2024年02月12日
    浏览(30)
  • (二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示

    提示:这里是该系列文章的所有文章的目录 第一章:(一)Qt下实现多个海康工业相机内触发采集回调取流显示 第二章:(二)Qt下多线程实现多个海康工业相机内触发采集回调取流显示 在本系列的上一篇文章中,我们讲述了实现海康工业相机的连接,采用内触发采集模式,

    2024年02月16日
    浏览(36)
  • C++并发与多线程笔记八:async、future、packaged_task、promise

    本文接上文 C++并发与多线程笔记七:condition_variable、wait、notify_one/all 的内容,主要记录 async、future、packaged_task、promise 概念以及用法。 2.1 基本用法 std::async 是个函数模板,用来启动一个异步任务,启动一个异步任务后,它返回一个 std::future 类模板对象。 上述\\\"启动一个异步

    2023年04月13日
    浏览(39)
  • C++ Qt开发:TableView与TreeView组件联动

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍 TableView 与 TreeView 组件联动的常用方法及灵活运用。 本章我们继续实现表格的

    2024年02月04日
    浏览(30)
  • VS开发QT项目,手写按钮槽函数避坑

    由于最近开发需要在VS2017上配置QT开发环境,进行QT项目的开发,之前从来没有这样使用过,在此记一些坑。 QT的槽函数是非常方便的,使用QT Creator可以自动生成代码,方便快捷。但是代码可读性不强,一些连接方面的信息都被隐藏了。由于之前一直使用QT Creator,所以其实还

    2023年04月13日
    浏览(27)
  • C++ Qt开发:Charts与数据库组件联动

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍 Charts 组件与 QSql 数据库组件的常用方法及灵活运用。 在之前的文章中详细介绍

    2024年02月03日
    浏览(32)
  • C++中的回调函数

    C++中的回调函数是指将一个 函数作为参数 传递 给另一个函数 ,并在另一个函数中 调用 该函数。 这种技术被称为函数指针或函数对象。 回调函数通常用于 异步编程 中,例如事件处理程序、GUI编程、网络编程等。 在这些情况下,程序需要在某个事件发生时执行某些操作,

    2024年02月06日
    浏览(38)
  • C++ Qt开发:数据库与TableView多组件联动

    Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍 TableView 组件与数据库联动的常用方法及灵活运用。 在Qt中,通常我们不会在

    2024年02月04日
    浏览(40)
  • 在QT中使用多线程并发服务器(C++)

    什么是多线程并发服务器?在QT里如何使用多线程并发服务器呢? 多线程并发服务器是一种网络服务器设计,它能够同时处理多个客户端的请求。在多线程服务器中,主线程负责监听和接受来自客户端的连接请求,每当有一个新的连接请求到来时,服务器就会创建一个新的线

    2024年04月11日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包