侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1824 篇文章
  • 累计收到 0 条评论

使用 async/await 处理简单异步任务

2025-12-12 / 0 评论 / 3 阅读

题目

使用 async/await 处理简单异步任务

信息

  • 类型:问答
  • 难度:⭐

考点

async/await 基本用法, Future trait 理解, tokio 运行时基础

快速回答

在 Rust 中处理异步任务的基本步骤:

  • 使用 async 关键字定义异步函数
  • 在函数内部用 await 等待其他异步操作完成
  • 使用 #[tokio::main] 属性标记主函数
  • 通过运行时(如 tokio)执行异步函数

示例核心代码:

#[tokio::main]
async fn main() {
    let result = fetch_data().await;
    println!("{}", result);
}

async fn fetch_data() -> String {
    "Data loaded".to_string()
}
## 解析

原理说明

Rust 的异步编程基于 Future trait:

  • async fn 会返回一个实现了 Future trait 的类型
  • .await 会暂停当前任务直到 Future 完成(非阻塞)
  • 需要运行时(如 tokio)来驱动 Future 的执行

完整代码示例

// 1. 添加依赖到 Cargo.toml
// [dependencies]
// tokio = { version = "1", features = ["full"] }

// 2. 示例代码
use std::time::Duration;

#[tokio::main]  // 创建tokio运行时
async fn main() {
    println!("程序开始");

    // 启动异步任务
    let task = tokio::spawn(async {
        println!("子任务开始");
        tokio::time::sleep(Duration::from_secs(1)).await;
        println!("子任务完成");
    });

    // 并行执行其他操作
    fetch_data().await;

    // 等待任务完成
    task.await.unwrap();
    println!("程序结束");
}

// 异步函数定义
async fn fetch_data() -> String {
    tokio::time::sleep(Duration::from_millis(500)).await;
    println!("数据获取完成");
    "Sample data".to_string()
}

最佳实践

  • 使用 #[tokio::main] 简化运行时启动
  • tokio::spawn 创建并发任务
  • 避免在异步函数中执行长时间阻塞操作(应使用 tokio::time::sleep 而非 std::thread::sleep
  • 使用 async/await 代替直接操作 Future trait

常见错误

  • 忘记添加 await 导致异步操作未执行
  • 在非异步函数中使用 .await
  • 未配置运行时(如缺少 #[tokio::main]
  • 混淆 std::thread::sleep(阻塞线程)和 tokio::time::sleep(异步等待)

扩展知识

  • Future 状态机:编译器将 async 代码转换为状态机
  • 运行时选择:tokio 是最常用运行时,另有 async-std、smol 等
  • 执行器(Executor):负责调度和执行 Future
  • Waker 机制:当 Future 可继续执行时通过 Waker 通知执行器