当前位置: 首页 > news >正文

C++ 异步编程脉络与示例

引言

异步编程是现代软件开发中不可或缺的一部分,尤其是在处理 I/O 操作、网络请求、用户界面响应等需要高并发场景时。C++ 作为一门底层语言,为开发者提供了多种异步编程的工具和方法。本文将系统地探讨 C++ 异步编程的发展历程,从早期的回调方法,到 std::futurestd::promise,再到现代的协程(coroutines),全面解析各个阶段的特点和使用方法。

1. 早期的回调方法

回调函数的基本概念

回调函数(Callback Function)是指将一个函数指针或函数对象作为参数传递给另一个函数,在异步操作完成后调用该回调函数处理结果。回调函数是一种常见的异步编程模式,广泛应用于事件驱动的编程模型中。

优缺点分析
  • 优点
    • 实现简单,易于理解。
    • 适用于简单的异步任务。
  • 缺点
    • 回调地狱(Callback Hell):嵌套的回调使代码难以维护。
    • 错误处理复杂:需要在每个回调中处理错误,容易遗漏。
    • 状态管理复杂:需要显式地管理状态,容易出错。
示例代码

以下是一个简单的示例,展示了如何使用回调函数进行异步操作:

#include <iostream>
#include <thread>
#include <functional>// 异步操作函数,接受一个回调函数作为参数
void asyncOperation(std::function<void(int)> callback) {std::thread([callback]() {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作callback(42); // 异步操作完成,调用回调函数}).detach(); // 分离线程
}int main() {// 调用异步操作,并传递回调函数asyncOperation([](int result) {std::cout << "Result: " << result << std::endl;});std::this_thread::sleep_for(std::chrono::seconds(3)); // 等待异步操作完成return 0;
}
实际应用

在图形用户界面(GUI)编程中,回调函数广泛用于事件处理。例如,按钮点击事件、鼠标移动事件等。在网络编程中,回调函数用于处理异步 I/O 操作,如数据接收、连接建立等。

2. Futures 和 Promises

引入背景

C++11 引入了 std::futurestd::promise,为异步编程提供了更结构化的工具。std::future 允许你获取异步操作的结果,而 std::promise 则用于设置这个结果。通过 std::async 可以轻松地启动异步任务,并获取其结果。

关键特性
  • std::future:用于表示异步操作的结果,可以通过 get() 方法获取结果。
  • std::promise:用于设置异步操作的结果,可以与 std::future 关联。
  • std::async:用于启动异步任务,可以选择异步或同步执行。
优缺点分析
  • 优点
    • 代码更加结构化,避免了回调地狱。
    • 支持异常处理,提供了更健壮的错误处理机制。
    • 易于组合多个异步操作。
  • 缺点
    • 仍然存在一定的复杂性,特别是在处理多个异步任务时。
    • 需要显式地管理 std::futurestd::promise 对象。
示例代码

以下是一个简单的示例,展示了如何使用 std::futurestd::promise 进行异步操作:

#include <iostream>
#include <future>
#include <thread>// 异步操作函数
int asyncOperation() {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作return 42;
}int main() {// 启动异步任务,并获取 future 对象std::future<int> result = std::async(std::launch::async, asyncOperation);std::cout << "Waiting for result..." << std::endl;// 获取异步操作的结果std::cout << "Result: " << result.get() << std::endl;return 0;
}

std::promisestd::future 是一对可以配合使用的工具。std::promise 用于设置异步操作的结果,而 std::future 用于获取这个结果。

示例代码

下面的代码展示了如何使用 std::promisestd::future 进行异步操作。

#include <iostream>
#include <thread>
#include <future>// 异步操作函数,接受一个 std::promise 对象
void asyncOperation(std::promise<int>& prom) {std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作prom.set_value(42); // 设置异步操作的结果
}int main() {// 创建 std::promise 对象std::promise<int> promise;// 获取与 promise 关联的 std::future 对象std::future<int> future = promise.get_future();// 启动一个线程执行异步操作,并传递 std::promise 对象std::thread t(asyncOperation, std::ref(promise));// 等待异步操作完成,并获取结果std::cout << "Waiting for result..." << std::endl;int result = future.get(); // 这会阻塞直到结果可用std::cout << "Result: " << result << std::endl;// 等待线程完成t.join();return 0;
}
实际应用

在需要等待多个异步操作完成后再进行处理的场景中,std::futurestd::promise 非常有用。例如,在并行计算、并发编程、网络请求等场景中,可以使用 std::async 启动多个异步任务,并使用 std::future 获取结果。在多线程编程中,可以使用 std::promise 将结果从工作线程传递到主线程。

3. 协程(Coroutines)

引入背景

C++20 引入了协程(coroutines),这是对异步编程的一次重大改进。协程允许函数在执行过程中暂停和恢复,这使得异步代码可以写得像同步代码一样简洁易读。协程的引入极大地简化了复杂异步场景下的代码编写。

关键特性
  • 暂停和恢复:协程可以在执行过程中暂停,并在需要时恢复。
  • 更好的代码结构:协程使得异步代码看起来像同步代码,易于阅读和维护。
  • 灵活性:协程可以与异步 I/O、事件驱动编程等结合使用,提供高效的异步处理能力。
优缺点分析
  • 优点
    • 代码更加简洁和易读。
    • 更加灵活,适用于各种复杂的异步场景。
    • 更好地支持异步流控制。
  • 缺点
    • 需要编译器和标准库的支持。
    • 对初学者可能有一定的学习曲线。
示例代码

以下是一个简单的示例,展示了如何使用协程进行异步操作:

#include <iostream>
#include <coroutine>
#include <thread>
#include <chrono>// 自定义的返回类型
struct Task {struct promise_type {Task get_return_object() { return {}; }std::suspend_never initial_suspend() { return {}; }std::suspend_always final_suspend() noexcept { return {}; }void return_void() {}void unhandled_exception() { std::terminate(); }};
};Task asyncOperation() {std::cout << "Start async operation..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作std::cout << "Async operation completed." << std::endl;co_return;
}int main() {asyncOperation();std::this_thread::sleep_for(std::chrono::seconds(3)); // 等待异步操作完成return 0;
}
实际应用

协程在需要处理复杂异步流程的场景中非常有用。例如,在网络编程中,协程可以用于处理异步 I/O 操作,使代码更加简洁和高效。在游戏开发中,协程可以用于实现复杂的事件驱动逻辑。

4. 综合对比与未来展望

综合对比
  • 回调函数
    • 优点:实现简单,适用于简单异步任务。
    • 缺点:代码难以维护,错误处理复杂。
  • Futures 和 Promises
    • 优点:代码结构清晰,支持异常处理。
    • 缺点:对于复杂异步任务仍显不足,需要显式管理对象。
  • 协程
    • 优点:代码简洁易读,灵活性高。
    • 缺点:需要编译器和标准库支持,有一定学习曲线。
未来展望

随着 C++ 标准的不断进化,异步编程将会变得更加简洁和高效。协程的引入只是一个开始,未来可能会有更多的库和框架基于协程,进一步简化异步编程的复杂性。此外,随着硬件性能的提升和多核处理器的普及,异步编程将在各个领域发挥越来越重要的作用。

写在最后

C++ 异步编程经历了从回调函数到 std::futurestd::promise,再到现代协程的演变。每一种方式都有其优缺点,理解这些不同的异步编程范式,有助于在实际开发中选择最合适的解决方案。通过不断学习和实践,我们可以更好地应对复杂的异步编程挑战,为用户提供更高效、更可靠的程序。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • web基础与HTTP
  • IEEE报告解读:存储技术发展趋势分析
  • 神经网络中的优化方法
  • 网络编程复习
  • 服务器模式
  • 【C++】-----多态及原理
  • 相机标定——小孔成像、相机模型与坐标系
  • 《数据结构(C语言版)第二版》第五章-树和二叉树(5.7 哈夫曼树及其应用)
  • 【AI学习】[2024北京智源大会]具身智能:具身智能关键技术研究:操纵、决策、导航
  • kafka 3.x 配置kerbos
  • 赋能未来园区:TSINGSEE视频AI智能管理平台如何引领园区管理智慧化转型
  • java selenium 设置代理,允许在其他环境中使用不同的IP访问
  • 分类预测 | Matlab实现PSO-XGBoost粒子群算法优化XGBoost的多特征分类预测
  • C# 方法的定义
  • JavaScript -- 总结 9 (小白)
  • Android单元测试 - 几个重要问题
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • IDEA 插件开发入门教程
  • JavaScript设计模式与开发实践系列之策略模式
  • Mysql优化
  • MySQL主从复制读写分离及奇怪的问题
  • Spring核心 Bean的高级装配
  • 分享几个不错的工具
  • 计算机常识 - 收藏集 - 掘金
  • 力扣(LeetCode)22
  • 那些被忽略的 JavaScript 数组方法细节
  • 使用common-codec进行md5加密
  • 原创:新手布局福音!微信小程序使用flex的一些基础样式属性(一)
  • 智能合约Solidity教程-事件和日志(一)
  • ​DB-Engines 12月数据库排名: PostgreSQL有望获得「2020年度数据库」荣誉?
  • ​LeetCode解法汇总518. 零钱兑换 II
  • ​创新驱动,边缘计算领袖:亚马逊云科技海外服务器服务再进化
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • ‌分布式计算技术与复杂算法优化:‌现代数据处理的基石
  • #define用法
  • #php的pecl工具#
  • ( )的作用是将计算机中的信息传送给用户,计算机应用基础 吉大15春学期《计算机应用基础》在线作业二及答案...
  • (20050108)又读《平凡的世界》
  • (2024,Vision-LSTM,ViL,xLSTM,ViT,ViM,双向扫描)xLSTM 作为通用视觉骨干
  • (42)STM32——LCD显示屏实验笔记
  • (k8s中)docker netty OOM问题记录
  • (第二周)效能测试
  • (二十三)Flask之高频面试点
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (七)微服务分布式云架构spring cloud - common-service 项目构建过程
  • (四)stm32之通信协议
  • (四)TensorRT | 基于 GPU 端的 Python 推理
  • (原創) 博客園正式支援VHDL語法著色功能 (SOC) (VHDL)
  • .NET 5种线程安全集合
  • [ Linux 长征路第五篇 ] make/Makefile Linux项目自动化创建工具
  • [ vulhub漏洞复现篇 ] Grafana任意文件读取漏洞CVE-2021-43798
  • [20180224]expdp query 写法问题.txt
  • [202209]mysql8.0 双主集群搭建 亲测可用