C++异步回调示例:多线程执行任务,主线程通过回调监测任务状态

1、回调函数

  回调函数定义:把函数的指针或者地址作为参数传递给另一个参数,当这个指针被用来调用其所指向的函数时,那么这就是一个回调的过程,这个被回调的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或者条件发生时由另外的一方调用的,用于对该事件或者条件进行响应,是在两个独立函数或者独立类通信的通道。

回调机制原理如下:

  1. 调用者不知道具体事件发生时需要调用的具体函数
  2. 被调函数不知道何时被调用,只知道需要完成的任务
  3. 当具体事件发生时,调用者通过函数指针来调用具体函数
  4. 回调机制中的调用者和被调函数互不依赖。

2、回调函数和普通函数的区别

   普通函数的调用过程如下:
1)主程序运行,遇到普通函数的调用后,进入被调用函数体内执行内容。
2)等待被调用函数执行完毕后,主程序继续往下执行。
3)从主程序的角度看,这个过程为“调用–>等待被调用函数执行完毕–>继续执行”。

   回调函数的调用过程如下:
1)主程序运行,遇到回调函数的调用后,发起调用;
2)主程序不等回调函数执行完毕,而是立即返回并继续往下执行。
3)调用程序执和被调用函数同时在执行。当被调函数执行完毕后,被调函数会反过来调用某个事先指定函数,以通知主程序;
这个过程称为回调(Callback),这正是回调函数名称的由来。

3、同步回调和异步回调

   回调函数分为同步回调和异步回调。同步回调可以是单线程也可以是多线程,如果多线程同步回调的话,主线程需要等待子线程回调完成后再继续执行。而异步回调必须是多线程或多进程(每个进程可以是单线程),异步回调必须依靠多线程或多进程才能完成。

(1) 同步回调:把函数b传递给函数a。执行a的时候,回调了b,a要一直等到b执行完才能继续执行;

(2) 异步回调:把函数b传递给函数。执行a的时候,回调了b,然后a就继续往后执行,b独自执行。

4、异步回调示例

4.1 示例说明

  下面我们来编写一个工作中常见的异步回调函数使用案例。案例说明:主线程发起任务,创建子线程来进行任务处理,同时主线程通过回调函数来检测任务进度状态,以便确认任务是否执行完成。

案例详情如图所示:

1)主线程传入任务参数;
2)创建子线程并传入参数;
3)主线程结束;
4)子线程启动开始工作;
5)通过回调函数监测任务执行状态。

在这里插入图片描述

4.2 示例源码

main.cpp

// main.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。#include "workThread.h"#include <iostream>
using namespace std;// 回调函数监测状态
bool OnStatusChangeCallBack(workParam& stuParam)
{if (stuParam.nStatus == -1){printf("Status: waiting! sInput: %s, sOutput: %s! \n", stuParam.sInput.c_str(), stuParam.sOutput.c_str());}else if(stuParam.nStatus == 0){printf("Status: begin! sInput: %s, sOutput: %s! \n", stuParam.sInput.c_str(), stuParam.sOutput.c_str());}else if (stuParam.nStatus == 1){printf("Status: midding! sInput: %s, sOutput: %s! \n", stuParam.sInput.c_str(), stuParam.sOutput.c_str());}else if (stuParam.nStatus == 2){printf("Status: finish! sInput: %s, sOutput: %s! \n", stuParam.sInput.c_str(), stuParam.sOutput.c_str());}return true;
}int main(int argc, char* args[])
{printf("The mainThread input workParam! \n");// 设定参数workParam stuParam;stuParam.nStatus = -1;stuParam.sInput = "myWorkdir";stuParam.sOutput = "xxx";printf("The mainThread create childThread! \n");// 创建子线程workThread myWork;myWork.setParam(stuParam);myWork.GetCallbackData(OnStatusChangeCallBack);printf("The mainThread is over! \n\n");return 0;
}

workThread.h

#pragma once#include <iostream>
#include <string>
#include <vector>
#include <thread>struct workParam
{workParam(){nStatus = -1;sInput = "";sOutput = "";}workParam& operator = (const workParam& src){nStatus = src.nStatus;sInput = src.sInput;sOutput = src.sOutput;return* this;}int nStatus;std::string sInput;std::string sOutput;
};typedef bool(*CallFun)(workParam& stuParam);class workThread
{
public:workThread();~workThread();void Realese();void setParam(const workParam& stuParam);void Run();CallFun m_callFun;void GetCallbackData(CallFun call_fun);
private:std::thread m_workThread;workParam m_stuParam;
};

workThread.cpp

#include "workThread.h"
#include <functional>
#include <windows.h>
using namespace std;workThread::workThread()
{
}workThread::~workThread()
{Realese();
}void workThread::Realese()
{m_workThread = std::thread(std::bind(&workThread::Run, this));if (m_workThread.joinable()){m_workThread.join();}
}void workThread::setParam(const workParam& stuParam)
{m_stuParam = stuParam;
}void workThread::Run()
{printf("The childThread is working! \n");{m_stuParam.nStatus = 0;m_callFun(m_stuParam);}for (int i = 0; i < 100; i++){if (i == 50){Sleep(1000);{m_stuParam.nStatus = 1;m_stuParam.sOutput = "D";m_callFun(m_stuParam);}}if (i == 99){Sleep(1000);{m_stuParam.nStatus = 2;m_stuParam.sOutput = "FF";m_callFun(m_stuParam);}}}
}void workThread::GetCallbackData(CallFun call_fun)
{m_callFun = call_fun;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/444.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Ubuntu20.04 ISAAC SIM仿真下载使用流程(4.16笔记补充)

机器&#xff1a;华硕天选X2024 显卡&#xff1a;4060Ti ubuntu20.04 安装显卡驱动版本&#xff1a;525.85.05 参考&#xff1a; What Is Isaac Sim? — Omniverse IsaacSim latest documentationIsaac sim Cache 2023.2.3 did not work_isaac cache stopped-CSDN博客 Is…

相机1:如何系相机肩带

开始解锁新领域&#xff0c;多看几个相关视频&#xff0c;大概也就可以掌握一两种系相机肩带的方法&#xff0c;本质就是新知识的学习过程&#xff0c;不可能等着或者期待出来一个完整的教程&#xff0c;一步一步自己去探索&#xff0c;自己去查资料。 目录 总述 第一步&#…

chrome 浏览器 f12 如何查看 websocket 消息?

1. 打开目标页面 2. f12--》网络--》WS&#xff0c;然后刷新页面( 如果不刷页面&#xff0c;就会看不到 websocket 请求&#xff0c;因为 websocket 是长连接&#xff0c;页面加载后只发出一次连接请求&#xff0c;不像 http 接口&#xff0c;不用刷新页面&#xff0c;待会儿也…

STM32F103 hal库 移植 freeRTos+LVGL

先配置freeRTOS 配置时钟 选用外部晶振 这里选用其他定时器&#xff0c;至于为什么我也不是很懂&#xff0c;好像说是跟稳定 配置FREERTOS 其他配置看着办 移植LVGL 先去gitee下载源码 选择一个版本 开始移植 1、添加lvgl源码到工程文件中 把lvgl-8.0.2\src文件夹直接复制…

SpringBoot(一)【入门】

前言 1、SpringBoot 快速入门 1.1、SpringBoot 简介 SpringBoot 是用来简化 Spring 应用的初始搭建以及开发过程 首先我们回顾一下 SpringMVC 项目的开发过程&#xff1a; 导入依赖&#xff08;javax.servlet-api 和 spring-webmvc&#xff09;Servlet 容器配置类&#xff…

227基于matlab的作业调度问题

基于matlab的作业调度问题。采用遗传算法&#xff0c;解决作业调度问题。一共三个作业&#xff0c;每个作业有不同的时间长度和紧急程度&#xff0c;超过时间会有惩罚措施。通过遗传算法计算出最好的作业安排&#xff0c;使得惩罚最小&#xff0c;获益最大。最终结果通过GUI用甘…

Maven 项目 JDK 8、JDK 17 多版本 Java 编译依赖最佳实践

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

ubuntu下交叉编译ffmpeg到目标架构为aarch架构的系统

Ubuntu下FFmpeg的aarch64-linux-gnu架构交叉编译教程 一、前言 有时候真的很想报警的&#xff0c;嵌入式算法部署花了好多时间了&#xff0c;RKNN 1808真是问题不少&#xff1b;甲方那边也是老是提新要求&#xff0c;真是受不了。 由于做目标检测&#xff0c;在C代码中有对视…

Kingbase(人大金仓数据库)(总结全网精华,虚拟机:从安装到操作数据库一条龙)

前言&#xff1a; 前一阵子一直在捣鼓人大金仓数据库&#xff0c;虽然国产化的数据库很值得夸赞&#xff0c;但是网上的资料确实少的可怜。特此记录一下我在学习这个数据库的心酸历程。 安装就看这个大哥的&#xff0c;我之前安装就是看的他的&#xff0c;非常靠谱。 linux安装…

Embedding例子:简单NN网络、迁移学习例子

一、简单例子&#xff1a;构造简单NN网络生成Embedding 1、pytorch例子 2、tensorflow例子 # 1导入模块 import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Embedding import numpy as np# 2构建语料库 corpus[[…

每日两题 / 22. 括号生成 54. 螺旋矩阵(LeetCode热题100)

22. 括号生成 - 力扣&#xff08;LeetCode&#xff09; dfs生成合法的括号序列即可 class Solution { public:vector<string> ans;void dfs(int l, int r, int n, string& s){if (s.size() n * 2){ans.push_back(s);return;}if (l){s "(";dfs(l - 1, …

Burpsuite插件 BurpAPIFinder专为未授权/敏感信息/越权而生

BurpAPIFinder 攻防演练过程中&#xff0c;我们通常会用浏览器访问一些资产&#xff0c;但很多未授权/敏感信息/越权隐匿在已访问接口过html、JS文件等&#xff0c;通过该Burp插件我们可以&#xff1a; 1、发现通过某接口可以进行未授权/越权获取到所有的账号密码、私钥、凭证 …

记录方式重新打开人生

文章目录 引言节省生命感知细节的能力正视痛苦总结 引言 你是否遇到以下问题 时间过得很快&#xff0c;不知道过去在忙什么事情很多很杂&#xff0c;感觉一直都很忙但是好像也没啥收获生活、工作中不顺心的事情很多&#xff0c;心里比较烦躁压抑 那么可以尝试参考《奇特的一…

python环境引用《解读》----- 环境隔离

首先我先讲一下Anaconda&#xff0c;因为我用的是Anaconda进行包管理。方便后面好理解一点。 大家在python中引用环境的时候都会经历下面这一步&#xff1a; 那么好多人就会出现以下问题&#xff08;我就是遇到了这个问题&#xff09;&#xff1a; 我明明下载了包&#xff0c…

吴恩达深度学习笔记:深度学习的 实践层面 (Practical aspects of Deep Learning)1.1-1.3

目录 第一门课&#xff1a;第二门课 改善深层神经网络&#xff1a;超参数调试、正 则 化 以 及 优 化 (Improving Deep Neural Networks:Hyperparameter tuning, Regularization and Optimization)第一周&#xff1a;深度学习的 实践层面 (Practical aspects of Deep Learning)…

阶段性学习汇报 4月19日

一、毕业设计和毕业论文 毕业设计后端功能基本实现&#xff0c;但是还有些具体的细节需要优化&#xff0c;例如这些图片的显示问题&#xff0c;前端只有个前端页面以及部分交互逻辑&#xff0c;还需进一步完善。我想在疾病预测这里加一个创新点&#xff0c;基于推荐算法。小程序…

测绘管理与法律法规 | 中华人民共和国测绘法 | 学习笔记

《中华人民共和国测绘法》笔记&#xff1a; 第一章 总则 第一条&#xff1a;立法目的&#xff0c;即加强测绘管理&#xff0c;促进测绘事业发展&#xff0c;保障测绘事业为经济建设、国防建设、社会发展和生态保护服务&#xff0c;维护国家地理信息安全。 第二条&#xff1a;…

网络爬虫软件学习

1 什么是爬虫软件 爬虫软件&#xff0c;也称为网络爬虫或网络蜘蛛&#xff0c;是一种自动抓取万维网信息的程序或脚本。它基于一定的规则&#xff0c;自动地访问网页并抓取需要的信息。爬虫软件可以应用于大规模数据采集和分析&#xff0c;广泛应用于舆情监测、品牌竞争分析、…

ollama大语言模型

查看已经安装的大语言模型 ollama list运行大语言模型 ollama run llama2:latest

Qt实现Mysql数据库的连接,查询,修改,删除,增加功能

Qt实现Mysql数据库的连接&#xff0c;查询&#xff0c;修改&#xff0c;删除&#xff0c;增加功能 安装Mysql数据库&#xff0c;QtCreator Mysql选择Mysql Server 8.1版本安装。 Mysql Server 8.1安装过程 1.首先添加网络服务权限&#xff1a; WinR键输入compmgmt.msc进入…