跳到主要内容

try_join

搜索

try_join 

Source
macro_rules! try_join {
    ($(biased;)? $($future:expr),*) => { ... };
}
展开描述

等待多个并发分支,当 所有 分支都以 Ok(_) 完成时返回, 或在第一个 Err(_) 时返回。

try_join! 宏必须在 async 函数、闭包和代码块内部使用。

类似于 join!try_join! 宏接受一组 async 表达式,并在同一任务上并发地对它们求值。每个 async 表达式都会被求值为一个 future,来自每个表达式的 future 会在当前任务上进行多路复用。try_join! 宏在所有 分支返回 Ok首个分支返回 Err 时返回。

§Notes

所提供的 future 是内联存储的,无需分配 Vec

§运行时特征

通过在当前任务上运行所有 async 表达式,这些表达式 能够并发运行,但不能并行运行。这意味着所有 表达式都在同一线程上运行,如果某个分支阻塞了该线程, 所有其他表达式将无法继续。如果需要并行执行, 可以使用 tokio::spawn 生成每个 async 表达式,并将 join handle 传给 try_join!

§公平性

默认情况下,try_join! 生成的 future 在每次被唤醒时, 都会轮换决定首先轮询哪个所包含的 future。

可以通过在宏的开头添加 biased; 来覆盖此行为。 详细信息请参见示例。这将使 try_join 按照 future 从上到下出现的顺序进行轮询。

如果你的 future 仍会交互,且知道探造的顺序是否重要,则可能需要这个宏。

但在这种模式下有一个重要的注意事项。确保 future 的 poll 顺序是公平的就成了你的 责任。例如,如果你要 join 一个流和一个关闭 future,且该流 每次 poll 时都有大量消息需要长时间处理, 那么你应该把关闭 future 放在 try_join! 列表的更前面, 以确保它始终被 poll,而不会因流 future 长时间返回 Poll::Pending 而被延迟。

§示例

两个分支的基本 try_join

async fn do_stuff_async() -> Result<(), &'static str> {
    // async work
}

async fn more_async_work() -> Result<(), &'static str> {
    // more here
}

let res = tokio::try_join!(
    do_stuff_async(),
    more_async_work());

match res {
    Ok((first, second)) => {
        // do something with the values
    }
    Err(err) => {
        println!("processing failed; error = {}", err);
    }
}

在已派生的任务上使用 try_join!

use tokio::task::JoinHandle;

async fn do_stuff_async() -> Result<(), &'static str> {
    // async work
}

async fn more_async_work() -> Result<(), &'static str> {
    // more here
}

async fn flatten<T>(handle: JoinHandle<Result<T, &'static str>>) -> Result<T, &'static str> {
    match handle.await {
        Ok(Ok(result)) => Ok(result),
        Ok(Err(err)) => Err(err),
        Err(err) => Err("handling failed"),
    }
}

let handle1 = tokio::spawn(do_stuff_async());
let handle2 = tokio::spawn(more_async_work());
match tokio::try_join!(flatten(handle1), flatten(handle2)) {
    Ok(val) => {
        // do something with the values
    }
    Err(err) => {
        println!("Failed with {}.", err);
    }
}

使用 biased; 模式来控制 poll 顺序。

async fn do_stuff_async() -> Result<(), &'static str> {
    // async work
}

async fn more_async_work() -> Result<(), &'static str> {
    // more here
}

let res = tokio::try_join!(
    biased;
    do_stuff_async(),
    more_async_work()
);

match res {
    Ok((first, second)) => {
        // do something with the values
    }
    Err(err) => {
        println!("processing failed; error = {}", err);
    }
}