Rust 异步编程高级应用指南

【Rust异步编程】Rust异步编程原理解析、标准库实现与第三方库实现详解 异步编程是一种允许程序在等待某些操作(如I/O)完成时继续执行其他任务的编程范式。与传统的同步编程相比,异步编程可以显著提高程序的吞吐量和资源利用率。 在Rust中,异步编程具有以下特点: 非阻塞执行:任务可以在等待时让出控制权 轻量级:异步任务(称为future)比线程更轻量 显式标记:使用async/await语法明确标识异步代码 阅读详情

Rust 异步编程高级应用指南

1. 什么是异步编程?

异步编程是一种编程范式,允许程序在等待 I/O 操作完成时继续执行其他任务,而不是阻塞线程。在 Rust 中,异步编程主要通过 async/await 语法和 tokio 等运行时库来实现。

async fn hello() {
    println!("Hello");
    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    println!("World");
}

fn main() {
    tokio::runtime::Runtime::new().unwrap().block_on(hello());
}

2. Future 特质

Future 是 Rust 中表示异步操作结果的特质,它定义了如何将异步操作转换为最终结果。

use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

struct MyFuture {
    count: u32,
}

impl Future for MyFuture {
    type Output = u32;
    
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        if self.count >= 5 {
            Poll::Ready(self.count)
        } else {
            // 告诉 executor 我们还没准备好
            cx.waker().wake_by_ref();
            Poll::Pending
        }
    }
}

3. 任务管理

3.1 生成任务

使用 tokio::spawn 可以生成一个新的异步任务,它会在后台执行。

async fn task1() -> String {
    tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
    "Task 1 done".to_string()
}

async fn task2() -> String {
    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    "Task 2 done".to_string()
}

async fn main() {
    let handle1 = tokio::spawn(task1());
    let handle2 = tokio::spawn(task2());
    
    let result1 = handle1.await.unwrap();
    let result2 = handle2.await.unwrap();
    
    println!("{result1}, {result2}");
}

3.2 任务取消

使用 AbortHandle 可以取消正在执行的任务。

use tokio::sync::oneshot;

async fn long_running_task() {
    for i in 0..10 {
        println!("Working... {i}");
        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    }
}

async fn main() {
    let (tx, rx) = oneshot::channel();
    
    let handle = tokio::spawn(async move {
        tokio::select! {
            _ = long_running_task() => {
                println!("Task completed");
            }
            _ = rx => {
                println!("Task cancelled");
            }
        }
    });
    
    // 等待一段时间后取消任务
    tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
    tx.send(()).unwrap();
    
    handle.await.unwrap();
}

4. 流 (Stream)

Stream 是 Rust 中表示异步序列的特质,类似于迭代器,但用于异步场景。

use tokio::stream::StreamExt;

async fn main() {
    let mut stream = tokio::stream::iter(vec![1, 2, 3, 4, 5]);
    
    while let Some(item) = stream.next().await {
        println!("Item: {item}");
    }
}

4.1 自定义流

use tokio::stream::{Stream, StreamExt};
use std::pin::Pin;
use std::task::{Context, Poll};

struct Counter {
    count: u32,
    max: u32,
}

impl Stream for Counter {
    type Item = u32;
    
    fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let self_mut = self.get_mut();
        
        if self_mut.count < self_mut.max {
            let value = self_mut.count;
            self_mut.count += 1;
            Poll::Ready(Some(value))
        } else {
            Poll::Ready(None)
        }
    }
}

async fn main() {
    let mut counter = Counter { count: 0, max: 5 };
    
    while let Some(item) = counter.next().await {
        println!("Count: {item}");
    }
}

5. 选择器 (Selector)

使用 tokio::select! 宏可以等待多个异步操作中的任意一个完成。

async fn task1() -> String {
    tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
    "Task 1 done".to_string()
}

async fn task2() -> String {
    tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
    "Task 2 done".to_string()
}

async fn main() {
    let handle1 = tokio::spawn(task1());
    let handle2 = tokio::spawn(task2());
    
    tokio::select! {
        result1 = handle1 => println!("Task 1 completed: {}", result1.unwrap()),
        result2 = handle2 => println!("Task 2 completed: {}", result2.unwrap()),
    }
}

6. 超时处理

使用 tokio::time::timeout 可以为异步操作设置超时。

async fn long_running_task() {
    tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
    println!("Task completed");
}

async fn main() {
    let result = tokio::time::timeout(
        tokio::time::Duration::from_secs(2),
        long_running_task()
    ).await;
    
    match result {
        Ok(_) => println!("Task completed within timeout"),
        Err(_) => println!("Task timed out"),
    }
}

7. 异步 I/O

7.1 异步文件操作

use tokio::fs;

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 读取文件
    let content = fs::read_to_string("example.txt").await?;
    println!("File content: {content}");
    
    // 写入文件
    fs::write("output.txt", "Hello, World!").await?;
    println!("File written successfully");
    
    Ok(())
}

7.2 异步网络操作

use tokio::net::{TcpListener, TcpStream};
use tokio::io::{AsyncReadExt, AsyncWriteExt};

async fn handle_client(mut socket: TcpStream) {
    let mut buffer = [0; 1024];
    
    loop {
        let n = match socket.read(&mut buffer).await {
            Ok(n) if n == 0 => return,
            Ok(n) => n,
            Err(e) => {
                eprintln!("Error reading from socket: {e}");
                return;
            }
        };
        
        if let Err(e) = socket.write_all(&buffer[0..n]).await {
            eprintln!("Error writing to socket: {e}");
            return;
        }
    }
}

async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    println!("Server listening on 127.0.0.1:8080");
    
    loop {
        let (socket, _) = listener.accept().await?;
        tokio::spawn(handle_client(socket));
    }
}

8. 实际应用场景

8.1 异步 HTTP 服务器

use warp::Filter;

async fn hello() -> Result<impl warp::Reply, warp::Rejection> {
    Ok(warp::reply::json(&serde_json::json!({
        "message": "Hello, World!"
    })))
}

#[tokio::main]
async fn main() {
    let routes = warp::path!("api" / "hello").and_then(hello);
    
    println!("Server starting on http://localhost:3030");
    warp::serve(routes)
        .run(([127, 0, 0, 1], 3030))
        .await;
}

8.2 异步数据库操作

use sqlx::postgres::PgPool;

async fn main() -> Result<(), sqlx::Error> {
    let pool = PgPool::connect("postgres://username:password@localhost:5432/database").await?;
    
    // 创建表
    sqlx::query(r#"
        CREATE TABLE IF NOT EXISTS users (
            id SERIAL PRIMARY KEY,
            name TEXT NOT NULL
        )
    "#).execute(&pool).await?;
    
    // 插入数据
    sqlx::query(r#"INSERT INTO users (name) VALUES ($1)"#)
        .bind("Alice")
        .execute(&pool)
        .await?;
    
    // 查询数据
    let users = sqlx::query!("SELECT * FROM users")
        .fetch_all(&pool)
        .await?;
    
    for user in users {
        println!("User: {} - {}", user.id, user.name);
    }
    
    Ok(())
}

9. 最佳实践

  1. 使用 async/await 语法:使用现代的 async/await 语法,而不是旧的 Future 组合器。
  2. 合理使用任务:对于需要并行执行的操作,使用 tokio::spawn 创建任务。
  3. 使用 select! 宏:对于需要等待多个异步操作的场景,使用 select! 宏。
  4. 处理超时:对于可能长时间运行的操作,使用 timeout 设置超时。
  5. 错误处理:使用 Result 类型和 ? 运算符处理异步操作中的错误。
  6. 使用 Stream 处理序列:对于异步序列,使用 Stream 特质。
  7. 避免阻塞:在异步代码中避免使用阻塞操作,如 std::thread::sleep。

10. 总结

Rust 的异步编程系统是一种强大的工具,特别适合 I/O 密集型任务。通过掌握其高级特性,我们可以编写更加高效、可维护的异步代码。

在实际应用中,我们可以使用异步编程构建高性能的网络应用、数据库操作和文件处理系统,充分发挥 Rust 的并发能力。

希望本文对你理解和应用 Rust 异步编程有所帮助!

Mac 不小心断开移动硬盘导致磁盘无法读取和加载(顺利解决!) Mac移动硬盘不正确断开连接导致无法读取加载的解决方法,亲测有效 阅读详情

相关推荐

OpenClaw记忆插件升级实战:从memory-lancedb-pro安装到AgentSkill封装

向量数据库作为现代AI应用的核心基础设施,通过将非结构化数据转换为高维向量并利用相似度检索实现语义理解。其原理基于嵌入模型生成向量表示,结合近似最近邻搜索算法实现高效查询。这项技术为智能体系统提供了长期记忆和上下文感知能力,显著提升了对话连贯性与任务执行效率。在AI智能体开发领域,向量数据库常用于知识库构建、对话历史管理和个性化推荐等场景。本文聚焦OpenClaw框架中memory-lancedb-pro插件的部署实践,针对**插件加载顺序**和**Apache Arrow依赖**两大常见痛点,通过封装成可

weixin_42525482的博客 640

【送书福利-第四十四期】《 深入Rust标准库》

本书深入分析了Rust标准库的源代码,并厘清了分析Rust标准库源代码的脉络。全书共14章。第1章对Rust标准库体系进行了概述性介绍;第2章分析了Rust的一些独特性;第3~8章分析了CORE库与ALLOC库,这两个库可用于编写操作系统内核与用户态应用程序;第9~13章分析了STD库,STD库仅用于编写用户态应用程序;第14章对异步编程进行了简单分析。本书试图以标准库的源代码为基础分析Rust的一些最本质的内容,从而加快程序员掌握Rust的进程。

8728

ADS1220 STM32硬件SPI驱动程序

前一段时间温故了下标准库,使用的是F1系列芯片,测试程序。

随风飘零翼的博客 5776

libSQL多语言开发实战指南

libSQL多语言开发实战指南 【免费下载链接】libsql tursodatabase/libsql: 是一个基于 C++ 的数据库访问库,它支持 SQLite、 MySQL、 PostgreSQL等多种数据库。适合用于 C++ 应用程序的数据库操作,特别是对于需要访问多种数据库的场景。特点是 C++ 数据库库、支持多...

gitblog_00781的博客 608

深入解析i2cdetect:从基础命令到高级读写操作

本文深入解析Linux下i2cdetect工具,从基础安装、总线扫描到高级读写操作。作为i2c-tools的核心组件,i2cdetect是硬件调试的得力侦探,能快速识别I2C总线上的设备地址。文章还涵盖了i2cdump、i2cset、i2cget等进阶工具,并介绍了如何在C程序中调用读写接口进行嵌入式开发,是掌握I2C通信调试的实用指南。

weixin_29189987的博客 372

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

VBA学习笔记6:将多个工作表中满足条件的数据汇总到同一个工作表

weixin_45355881的博客 4708

【Rust异步】async和await异步编程实战:高并发任务处理全解析

async 和 await 是 Rust 中用于异步编程的关键字。 async 用于定义异步函数,表示函数体中包含异步代码。 await 用于等待异步操作完成,并返回异步操作的结果。 • 异步函数使用 async 关键字定义,并返回实现了 Future Trait 的类型。 异步函数可以在其他异步函数中使用 await 关键字等待异步操作完成。 调用异步函数时,会返回一个实现了 Future Trait 的对象,可以通过调用.await 方法等待结果。

景天科技苑 2万+

JS实例(三)图片的缓慢放大和缩小

  我们经常能看到在一些网站中可以通过按钮实现对图片的放大或者缩小,也有可能是鼠标经过时图片放大。在本例中就是通过JavaScript实现图片的放大和缩小。   首先是进行简单的页面布局 1 <div class="imagedispose"> 2 <img src="1.jpeg" id="imaged" width="400px" height="3...

weixin_34235105的博客 314

深入Rust标准库:必备的Rust语言高级指南

Rust标准库是Rust语言的核心组成部分,提供了丰富的功能和工具,包括数据结构、文件操作、多线程支持、网络编程等。它由多个模块组成,每个模块都提供了特定领域的功能。:提供了各种常用的集合类型,如VecHashMapHashSet等,用于存储和管理数据。std::fs:用于文件和目录的操作,包括文件的读写、目录的遍历和文件属性的获取等。:提供了多线程编程的支持,包括线程的创建、同步和通信等功能。std::net:用于网络编程的支持,包括TCP和UDP协议的socket编程、地址解析等功能。

努力是为了站在万人之中,成为别人的光 4万+

CMOS图像传感器——Remosaic技术

对remosaic技术进行了介绍

沧海一升的博客 9585

喷涂机器人系列编程:ABB IRB 5500_(9).常见故障诊断与排除

ABB IRB 5500 喷涂机器人在实际应用中可能会遇到各种故障,但通过系统的诊断和排除方法,可以确保生产线的连续运行。定期维护和保养是预防故障的重要手段,而操作培训和规范则能有效减少人为因素引起的故障。希望本节内容能帮助操作和维护人员提高故障诊断和排除的效率,确保喷涂机器人的稳定运行。如果您有任何疑问或需要进一步的帮助,请联系 ABB 客户服务中心。

zhubeibei168的博客 1045

Rust 异步编程深入浅出指南

Rust异步编程解析:Rust通过Future、async/await和执行器(如tokio)实现高效异步编程,适用于高并发场景。核心机制包括Waker通知系统、异步I/O和轻量级任务调度,并发模式提供select!、异步锁和流处理工具。开发需注意避免阻塞操作、限制并发数,并遵循结构化并发原则。调试时可使用异步堆栈追踪和监控工具,常见陷阱包括任务阻塞和Future未推进问题。Rust的异步模型兼具安全性与高性能,是构建现代网络服务的理想选择。

萧曳丶 1124

剪映专业版教程:用AI生成音乐MV并重新制作画面—《漂泊与归梦》完全原创实战

本文详细拆解如何用AI生成音乐MV并重新制作画面的全流程。以歌曲《漂泊与归梦》为例,首先用AI将歌词转化为带音乐的MP4文件;导入剪映后分离音频并删除原视频,通过“识别字幕”功能提取歌词文本并逐句核对修正;接着设置“向右擦除”动画并锁定字幕轨道;最后根据歌词意境配置动漫、风景等非真人画面规避审核风险。教程涵盖从AI生成、音频分离、字幕提取到画面重制的每个环节,助你打造完全原创、无侵权风险的音乐短视频。

深耕计算机专业知识与技术。 1079

Rust异步编程 Async Await 入门

要了解什么是异步代码,我们首先来谈谈同步代码。println!println!上述语句按照明确的顺序执行,从上到下一个接一个地执行。” 打印,然后读取并打印Cargo.toml的内容。这种模式在正常操作下非常好 - 但有时代码需要在当前上下文在等待其他内容时暂停 - 这通常称为阻塞。换句话说,当一段代码被阻塞时,它实际上处于暂停状态,等待特定操作完成才能继续。例如,当等待文件系统、网络通信、数据库事务甚至一段时间过去时,就会发生这种情况。在此阻塞状态期间,程序保持空闲状态,无法同时执行其他任务。

xuejianxinokok的专栏 1657

贝叶斯统计 [韦来生编]

贝叶斯(Bayes)统计是近几十年来迅速发展起来的数理统计的一个重要分支。贝叶斯方法与经典统计方法的主要不同之处是进行统计推断时除了利用样本信息外,还要利用参数的先验信息,因此可以提高统计推断或统计决策的效果。它在经济、金融、生物、医学、自然科学和社会科学等许多领域具有广泛的应用。贝叶斯方法的研究已渗透到了统计学的几乎所有领域。作者在给中国科学技术大学概率论与数理统计专业本科生开设的“数理统计”课程中有一章专门讲授“贝叶斯方法和统计决策理论”,近十年来也给中国科学技术大学概率统计专业研究生开设过几次“贝叶斯分析”课。本书是在对过去讲稿的内容作了适当的增减和调整的基础上完成的。  本书共分六章。第1章是绪论,介绍了贝叶斯统计的若干基本概念,同时对必要的数理统计的基础知识有重点地作了回顾。第二章介绍了确定先验分布的若干可供选择的方法。第三章介绍了几类常见统计模型参数的后验分布的主要结果和计算方法。第四章和第五章分别介绍了“贝叶斯统计推断”和“贝叶斯统计决策”的内容。第六章介绍了贝叶斯统计计算的若干方法,包括蒙特卡洛方法和马尔可夫链蒙特卡洛(MCMC)方法以及相关统计软件的简介。本书的每一章附右大量的例题和习题,书末附有常用的几个表格和部分习题解答供读者查用。  大约可在54学时内讲授本书的第1章至第六章的主要内容,教师可根据学时需要选讲本书第1章至第六章的部分内容。书中标“*”号的章节可略去不讲,留给读者作为阅读材料。第六章例题中的R代码和部分例题的数据文件等可从作者个人主页下载。  作者在编写本书的过程中参考了J.O.Berger教授的《统计决策论及贝叶斯分析》和茆诗松教授编写的《贝叶斯统计》等书中的一些内容,以及《贝叶斯分析》一书中由张伟平博士编写的有关贝叶斯统计计算的一些内容。在此表示衷心感谢。  本书编写准备过程中,中国科学技术大学统计与金融系的几个研究生帮助完成了本书部分中文的录入和排版,作者对他们的辛勤工作表示真诚的感谢。高等教育出版社为本书的出版给予了大力支持。在此一并致谢。

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

异步编程革命:Rust async/await完全指南

异步编程革命:Rust async/await完全指南 本文深入探讨了Rust异步编程的核心机制,从Future执行模型与任务调度机制、Pin和Unpin的内存安全原理,到Stream流处理与多Future并发技术,最后通过异步Web服务器实战开发展示完整应用。文章详细解析了Rust异步编程的底层实现原理和高级应用技巧,为开发者提供从基础到实战的完整指南。 Future执行模型与任务调度机制 在R...

gitblog_00027的博客 1263

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Rust 异步编程详解(async/await)

Rust异步编程通过async/await语法和Future trait实现高效I/O处理,核心机制包括状态机模型和运行时调度。文章详细解析了异步编程基础、核心组件(Future trait、async/await语法)、工作流程,并提供了HTTP请求等代码示例。同时探讨了错误处理、任务取消、Pin/Unpin等高级话题,比较了不同运行时的适用场景。最佳实践建议选择合适运行时、避免阻塞操作,并指出异步编程在性能和安全方面的优势,以及调试复杂度等限制。附带的并发网络请求示例展示了tokio运行时的实际应用,包

本博客分享软硬件一体化开发实战。硬件涵盖 PCB 设计、STM32 等 MCU 底层开发;软件包含 C++、Rust,Qt/QML、PyQt、Slint、TouchGFX、LVGL 各类 GUI 框架。方便软硬件开发者查阅学习。欢迎关注! 2224

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

详解Rust异步编程

Rust的异步编程通过async/await语法和Future特性提供了一种高效的方式来处理并发任务,尤其在I/O密集型操作中表现出色。async/await异步编程模型性能高,还能支持底层编程,同时又像线程和协程那样无需过多的改变编程模型,但async模型的问题就是内部实现机制过于复杂,对于用户来说,理解和使用没有线程和协程简单。

yang1fei2的博客 3150

Rust 异步编程实战

在复杂的应用中,定义自定义错误类型可以提高代码的可读性和可维护性。write!(f, "{:?}", self)async-std提供了一个简化的异步编程接口,与 Rust 标准库接口相似,使得异步编程更易于理解。println!("获取的数据: {}", data);});Tokio是一个功能强大的异步运行时,适用于构建 I/O 密集型应用。它支持异步 I/O、任务调度和定时器等功能。// 模拟异步延迟println!("延迟完成");

好看资源网的博客 1182

Rust异步编程指南

Rust异步编程指南 项目介绍 areweasyncyet.rs 是一个由Rust语言社区维护的项目,旨在跟踪Rust语言中异步编程功能的进展情况。该项目不仅提供了关于Rust异步编程的最新状态更新,还收集了相关的RFC、讨论和实现细节。通过这个项目,开发者可以了解到Rust异步编程的当前状态、已解决的问题以及未来的发展方向。 项目快速启动 安装Rust 首先,确保你已经安装了Rust编程语言。你...

gitblog_00403的博客 522

【Rust中的异步编程】

rust中的异步模型,实际上是使用future(能产出值的异步计算),通过轮询,挂起,唤醒,执行等操作来实现异步,runtime依赖tokio。Tokio是一个Rust 异步运行时库,底层基于epoll/kqueue这样的跨平台多路IO复用以及event loop,目前正在支持io_uring。其线程会执行task,可以充分利用多核,而Task 线程是Rust基于Future抽象出的一种绿色线程,因为不需要预先分配多余的栈内存,可以创建大量的Task,很适合做IO密集型应用。fn poll(

m0_37719524的博客 1676
上一篇: Python Web 开发高级应用指南
下一篇: Rust 错误处理高级应用指南
第一程序员
博客等级 码龄1年 1万+粉丝 1822原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值