事件驱动编程与异步编程:原理、对比及实践案例

在这里插入图片描述

在编程领域,事件驱动编程(Event-Driven Programming)与异步编程(Asynchronous Programming)是两种极为关键的编程范式,它们对于提升程序运行效率与响应速度效果显著,尤其在应对I/O密集型任务以及并发场景时,更是展现出了不可或缺的价值。对于初学者而已,这两个概念容易混淆,下面,我们将介绍一下二者的工作原理、对比它们的异同,并给出相应的代码示例。

一、原理解读

事件驱动编程

事件驱动编程的运行逻辑基于事件的触发。程序的核心任务是监听各类事件,这些事件涵盖范围广泛,诸如用户的输入操作、网络请求的到达、定时器触发等。每当一个事件发生时,与之对应的事件处理程序(也被称作事件处理器或者回调函数)便会被激活,以此对事件做出响应。整个程序并不主动去规划执行顺序,而是处于一种被动响应的状态,其关键支撑机制便是事件循环(Event Loop),它如同一个调度中枢,持续不断地监听事件,并精准地把事件分发给对应的处理器。

异步编程

异步编程允许程序发起一项操作之后,无需立刻停顿下来等待该操作完成,而是能够接着去执行其他的任务。待操作执行结束,程序会借助特定的机制获取通知,进而处理操作结果,常见的通知机制包含回调函数、Promise、async/await 等。这其中的核心要点在于非阻塞I/O,它让程序在等待I/O操作完结的过程中,依然能够维持运转,避免因等待而陷入停滞。

二、关联与差异

关联之处

在实际的编程实践里,事件驱动编程与异步编程常常携手合作。例如,在搭建网络服务器时,会采用事件驱动模型来监听客户端的连接请求(这属于典型的事件监听),一旦有新的连接请求抵达,服务器便会以异步的方式去处理该连接,这样一来,监听其他连接的工作并不会受到阻塞,从而保障了服务器的高效运行。

差异所在

  • 驱动源头差异:事件驱动编程的启动源于外部事件的发生,程序依据事件的出现来推进执行;而异步编程则是由程序自身率先发起异步操作,后续等待操作完成的通知。
  • 关注重点差异:事件驱动编程侧重于从整体架构层面规划程序,精心安排事件的调度逻辑;异步编程把目光聚焦于单个操作具体的执行方式,致力于优化操作执行的流程。
  • 实现手段差异:事件驱动编程通常依赖于事件循环以及事件队列这类机制来达成;异步编程的实现途径更为多样,像是回调函数、Promise、async/await,甚至线程、协程等技术手段均可运用。

三、C++ 代码示例详解

下面的代码旨在实现从文件中异步读取数据,并在读取完成后打印文件内容,借此展现两种编程范式的不同实现方式。

异步编程示例(使用 std::asyncstd::future

#include <iostream>
#include <fstream>
#include <future>
#include <string>std::string readFileAsync(const std::string& filename) {// 使用 std::async 异步读取文件auto future = std::async(std::launch::async, [&]() {std::ifstream file(filename);if (!file.is_open()) {return std::string("Error opening file");}std::string content((std::istreambuf_iterator<char>(file)),(std::istreambuf_iterator<char>()));return content;});// 在读取文件的同时可以执行其他任务std::cout << "Doing other work while reading file..." << std::endl;// 获取异步操作的结果(会阻塞直到读取完成)return future.get();
}int main() {std::string filename = "example.txt"; // 请确保该文件存在std::string fileContent = readFileAsync(filename);std::cout << "File content:\n" << fileContent << std::endl;return 0;
}

在此示例中,std::async 函数发起了一个异步读取文件的任务。尽管 future.get() 最终会等待文件读取完毕,但在这之前,主线程能够腾出手来执行其他事务。

事件驱动编程示例(使用 libevent 库)

#include <iostream>
#include <fstream>
#include <string>
#include <event2/event.h>void readCallback(evutil_socket_t fd, short event, void* arg) {if (event & EV_READ) {char buffer[1024];int bytesRead = read(fd, buffer, sizeof(buffer));if (bytesRead > 0) {std::string content(buffer, bytesRead);std::cout << "File content:\n" << content << std::endl;}event_base_loopbreak(static_cast<event_base*>(arg)); // 退出事件循环}
}int main() {std::string filename = "example.txt"; // 请确保该文件存在// 创建事件基event_base* base = event_base_new();// 打开文件evutil_socket_t fd = open(filename.c_str(), O_RDONLY);if (fd == -1) {std::cerr << "Error opening file" << std::endl;return 1;}// 创建事件event* ev = event_new(base, fd, EV_READ, readCallback, base);// 添加事件到事件基event_add(ev, NULL);std::cout << "Waiting for file to be read (event-driven)..." << std::endl;// 进入事件循环event_base_dispatch(base);// 清理event_free(ev);event_base_free(base);close(fd);return 0;
}

(编译需要链接libevent库,例如:g++ -o event_driven event_driven.cpp -levent
在这个例子里,借助 libevent 库构建起了一个简单的事件驱动程序。readCallback 函数扮演着事件处理器的角色,一旦文件变为可读状态,它便会被调用。程序通过 event_base_dispatch 指令进入事件循环,静候事件发生。

四、Python:结合应用场景案例

python实现这两者更加方便,在一个场景实现中,使用两者来看他们协调工作。
在网络爬虫这类应用场景中,事件驱动与异步编程相结合,能极大提升程序效能。以下是一段Python代码示例:

import asyncio
import aiohttpasync def fetch(session, url):async with session.get(url) as response:return await response.text()async def main():urls = ['https://example.com', 'https://another-site.com']async with aiohttp.ClientSession() as session:tasks = []for url in urls:task = asyncio.create_task(fetch(session, url))tasks.append(task)results = await asyncio.gather(*tasks)for result in results:print(result)loop = asyncio.get_event_loop()
loop.run_until_complete(main())

这段代码里,asyncio 库开启了异步编程模式,多个网络请求能够并发执行,这得益于异步编程减少等待时间的特性。而整个流程又依托于事件循环来管理调度,当某个请求完成时,便如同事件被触发,对应的处理代码得以运行,巧妙融合了事件驱动的思路。这一结合让爬虫能够更迅速地抓取网页内容,显著提升运行效率。

五、总结

总而言之,异步编程专注于保障单个操作的非阻塞执行,而事件驱动编程着眼于雕琢程序的整体架构与事件调度体系。在众多实际项目里,将二者有机结合,能够充分发挥各自优势,让程序在复杂的任务场景下,兼具高效性与稳定性。

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

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

相关文章

基于earthSDK三维地图组件开发

上效果 功能点 测量分析相机位置切换geojson数据加载地图打点&#xff0c;显示信息点击回传数据二三位切换 这里二三维切换通上篇openlayers分享&#xff0c;技术交流V:bloxed <template><div class"h100 w100"><div style"width:100%; heig…

计算机毕业设计Python+Spark知识图谱酒店推荐系统 酒店价格预测系统 酒店可视化 酒店爬虫 酒店大数据 neo4j知识图谱 深度学习 机器学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

RK3506开发板:智能硬件领域的新选择,带来卓越性能与低功耗

在现代智能硬件开发中&#xff0c;选择一款性能稳定、功耗低的开发板是确保产品成功的关键。Rockchip最新推出的RK3506芯片&#xff0c;凭借其卓越的能效比、多功能扩展性和优秀的实时性能&#xff0c;已经成为智能家电、工业控制、手持终端等领域的热门选择。而基于RK3506的Ar…

【AIGC-ChatGPT进阶副业提示词】星际占卜师:探索星象能量的艺术【限时免费阅读,一天之后自动进入进阶课程】

引言 在这个数字化的时代&#xff0c;我们创造了一个独特的角色 —— 星际占卜师。这不仅是一个简单的运势预测工具&#xff0c;更是一个融合了玄学、预言和能量解读的智能向导。通过精心设计的系统提示词和独特的画境生成机制&#xff0c;星际占卜师能够为用户带来沉浸式的占…

机器学习之PCA降维

主成分分析&#xff08;PCA&#xff0c;Principal Component Analysis&#xff09; 主成分分析&#xff08;PCA&#xff09;是一种常见的无监督学习技术&#xff0c;广泛应用于数据降维、数据可视化以及特征提取等任务。PCA的目标是通过线性变换将数据从高维空间映射到低维空间…

SOTA简繁中文拼写检查工具:FASPell Chinese Spell Checker 论文

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法&#xff0c;如果提升 100W 倍的性能&#xff1f; NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正&#xff1f;可我只会写 CRUD 啊&#xff01; 一个提升英文单词拼…

Visual Studio Code历史版本下载

本章教程&#xff0c;介绍如何找到Visual Studio Code的历史版本官方下载地址。 一、历史版本下载地址 下载地址&#xff1a;https://code.visualstudio.com/updates/ 二、常用版本下载地址 August 2017 (version 1.16)&#xff1a;https://code.visualstudio.com/updates/v1_…

Kubernetes(k8s)离线部署DolphinScheduler3.2.2

1.环境准备 1.1 集群规划 本次安装环境为&#xff1a;3台k8s现有的postgreSql数据库zookeeper服务 1.2 下载及介绍 DolphinScheduler-3.2.2官网&#xff1a;https://dolphinscheduler.apache.org/zh-cn/docs/3.2.2 官网安装文档&#xff1a;https://dolphinscheduler.apach…

【自动化测试】windows下安装Selenium浏览器界面测试工具

Date: 2024.12.23 10:15:53 author: lijianzhan 简述&#xff1a;这篇教程详细介绍了如何在Windows环境下安装selenium&#xff0c;并设置Chrome浏览器驱动。什么是Selenium&#xff1f;Selenium是一个基于浏览器的自动化测试工具&#xff0c;它提供了一种跨平台、跨浏览器的端…

如何在 Ubuntu 22.04 上安装 phpMyAdmin

简介 PHPMyAdmin 是在 Ubuntu 22.04 上管理 MySQL 数据库的绝佳选择。它是一个流行的工具&#xff0c;拥有简单、高效且用户友好的基于 Web 的界面&#xff0c;让你能够轻松地管理 MySQL 数据库。因此&#xff0c;许多开发人员、数据库管理员和网站所有者都信任 PHPMyAdmin 来…

大数据-256 离线数仓 - Atlas 数据仓库元数据管理 正式安装 启动服务访问 Hive血缘关系导入

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

[Python3] Sanic中间件

在 Sanic 中&#xff0c;中间件&#xff08;middleware&#xff09;是指在请求和响应之间执行的代码。它们是一个非常强大的工具&#xff0c;用于处理请求的预处理、响应的后处理、全局错误处理、日志记录、认证、权限校验、跨域资源共享&#xff08;CORS&#xff09;等任务。中…

使用 OpenCV 绘制线条和矩形

OpenCV 是一个功能强大的计算机视觉库&#xff0c;它不仅提供了丰富的图像处理功能&#xff0c;还支持图像的绘制。绘制简单的几何图形&#xff08;如线条和矩形&#xff09;是 OpenCV 中常见的操作。在本篇文章中&#xff0c;我们将介绍如何使用 OpenCV 在图像上绘制线条和矩形…

操作系统课程设计

摘 要 本项目旨在深入设计与实现一套基于Java的模拟操作系统&#xff0c;模拟和实现常见操作系统的核心功能&#xff0c;包括进程管理、内存分配与调度、高效的文件系统和多样化设备的管理。通过该模拟操作系统的开发&#xff0c;探索计算机操作系统的基础理论与实际工程细节…

css改变输入右下角图标

前言 正常情况下&#xff0c;HTML textarea 多行文本输入框会存如下图所示图标&#xff0c; 用户可拉动它改变高度&#xff0c;这是我们不想看到的&#xff0c;所以要去掉它。 去掉后&#xff1a; 解决方案 设置 resize 属性即可&#xff0c;如下代码所示&#xff1a; <…

HTML-CSS(day01)

W3C标准&#xff1a; W3C&#xff08; World Wide Web Consortium&#xff0c;万维网联盟&#xff09; W3C是万维网联盟&#xff0c;这个组成是用来定义标准的。他们规定了一个网页是由三部分组成&#xff0c;分别是&#xff1a; 三个组成部分&#xff1a;&#xff08;1&…

2024-12-24 NO1. XR Interaction ToolKit 环境配置

文章目录 1 软件配置2 安装 XRToolKit3 配置 OpenXR4 安装示例场景5 运行测试 1 软件配置 Unity 版本&#xff1a;Unity6000.0.26 ​ 2 安装 XRToolKit 创建新项目&#xff08;URP 3D&#xff09;&#xff0c;点击进入 Asset Store。 进入“Unity Registry”页签&#xff0…

C语言基础——指针(4)

一&#xff0e; 字符指针变量 字符指针变量的使用和整型指针变量的使用方法相似&#xff0c;以下是其基本使用方法的例子&#xff1a; &#xff08;1&#xff09;字符指针变量还有一种使用方法&#xff1a; const char* p "abcd" 需…

week 11 - BCNF

1. More on functional dependencies (功能依赖的更多内容) Lossless decomposition (无损分解) 研究如何在分解表的过程中不丢失信息&#xff0c;也就是说&#xff0c;通过分解后的表可以无损地重建原始表。 2. BCNF (Boyce-Codd Normal Form, BCNF范式) &#xff08;1&…

嵌入式学习-QT-Day06

嵌入式学习-QT-Day06 六、多窗口编程 1、QMessageBox 消息对话框 2、QWidget类 3、parent参数 4、堆栈窗口&#xff08;QStackedWidget&#xff09; 5、新建自定义窗口类 6、对象传值 6.1 父对象 → 子对象 6.2 子对象 → 父对象 7、事件机制 8、QMainWindow主窗口类 8.1 QMenu…