Skip to content

快速开始

  1. cargo new rust-async-demo 创建项目, 在 Cargo.toml 中添加 futures 依赖包
  2. 在 src/main.rs 中输入如下代码, 运行查看效果
rust
use futures::executor::block_on;
async fn say_hi() {
    println!("hi");
}

async fn say_hello() {
    println!("hello");
}

async fn say_hey() {
    println!("hey");
}

fn main() {
    // 1.此时并没有输出(说明函数并没有直接执行)
    let fut_hi = say_hi();
    let fut_hello = say_hello();
    let fut_hey = say_hey();

    println!("###main###");

    // 2.执行到此时才会输出(说明函数此时才真正执行)
    block_on(fut_hello);
    block_on(fut_hi);
    block_on(fut_hey);

    // 3. 异步函数执行顺序:
    // 先输出 hello, 然后在输出 hi 和 hey
    // 说明先执行的 say_hello 然后执行的 say_hi 和 say_hei
    // 也就是说, 哪个异步函数的返回值先被传入 block 谁就先执行
}
rust
[package]
name = "rust-async-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
futures = "0.3.31"

解析

异步函数的返回值

rust
// 接收一个实现 Future 特性的实例
fn my_block_on<T: Future>(f: T) {}

async fn say_hi() {
    println!("hi");
}

fn main() {
  my_block_on(say_hi());
  // 这个代码并没有报错, 那么也就说明:
  // say_hi 就是返回了一个 实现了 Future 特性的实例
  // 否则代码应该报错, 类型不匹配才对
}

block_on 函数的作用

  • 阻塞当前线程, 直到传入的 Feture 实例(或者说异步函数的返回值) 运行完成
rust
use futures::executor::block_on;
async fn say_hi() {
    println!("hi");
}
async fn say_hello() {
    println!("hello");
}
async fn say_hey() {
    println!("hey");
}

fn main() {
    let fut_hi = say_hi();
    let fut_hello = say_hello();
    let fut_hey = say_hey();

    // 1. 输出: ###main###
    println!("###main###");

    // 2. 输出: hello
    block_on(fut_hello);

    // 3. 输出: hi
    block_on(fut_hi);

    // 4. 输出: hey
    block_on(fut_hey);
}

WARNING

由代码的输出顺序可知, block_on 函数肯定会阻塞当前线程(主线程), 等待当前 block_on 中的 Future 实例执行完成, 然后(主线程)继续向下执行

上面这个代码既然会阻塞当前线程, 我直接同步执行不就完了吗? 那还要 Future 干嘛?

这时候就需要用到 await 关键字来代替 block_on

await 关键字

阻塞线程, 直至异步函数返回的 Future 执行完

rust
use std::thread::sleep;
use std::time::Duration;
use futures::executor::block_on;

async fn sit_down() {
    sleep(Duration::from_secs(1));
    println!("坐沙发");
}

async fn have_lunch() {
    sleep(Duration::from_secs(1));
    println!("吃午餐");
}

async fn watch_tv() {
    sleep(Duration::from_secs(1));
    println!("看电视");
}

async fn listen_music() {
    sleep(Duration::from_secs(1));
    println!("听音乐-来自电视")
}

async fn async_main() {
    println!("async-main-start");

    let fut1 = watch_tv();
    let fut2 = listen_music();

    // 2. await 关键字会等待 Future 执行完
    println!("before: sit_down and have_lunch");
    sit_down().await;
    have_lunch().await;
    println!("after: sit_down and have_lunch");

    // 3. futures::join! 宏也会等待 Future 执行完
    futures::join!(fut1, fut2);

    println!("async-main-end");
}

fn main() {
    println!("main-start");

    // 1.阻塞线程, 等待 async_main 的返回值(Future实例)执行完
    block_on(async_main()); 

    println!("main-end");
}

Released under the MIT License.