跳到主要内容

JoinSet

搜索

结构体 JoinSet 

源代码
pub struct JoinSet<T> { /* 私有字段 */ }
展开描述

在 Tokio 运行时上生成的任务的集合。

JoinSet 可用于等待集合中部分或全部任务的完成。该集合是无序的,任务将按其完成的顺序返回。

所有任务必须具有相同的返回类型 T

JoinSet 被 drop 时,JoinSet 中的所有任务都将立即中止。

§示例

生成多个任务并等待它们。

use tokio::task::JoinSet;

let mut set = JoinSet::new();

for i in 0..10 {
    set.spawn(async move { i });
}

let mut seen = [false; 10];
while let Some(res) = set.join_next().await {
    let idx = res.unwrap();
    seen[idx] = true;
}

for i in 0..10 {
    assert!(seen[i]);
}

§Task ID guarantees

当一个任务在 JoinSet 中被跟踪时,该任务的 ID 相对于 Tokio 中所有其他正在运行的任务是唯一的。为此,在 JoinSet 中跟踪任务等同于持有该任务的 JoinHandle。有关详细信息,请参阅任务 ID 文档。

实现§

源代码§

impl<T> JoinSet<T>

源代码

pub fn new() -> Self

创建一个新的 JoinSet

源代码

pub fn len(&self) -> usize

返回 JoinSet 中当前的任务数。

源代码

pub fn is_empty(&self) -> bool

返回 JoinSet 是否为空。

源代码§

impl<T: 'static> JoinSet<T>

源代码

pub fn spawn<F>(&mut self, task: F) -> AbortHandle
where F: Future<Output = T> + Send + 'static, T: Send,

JoinSet 上生成提供的任务,返回一个可用于远程取消任务的 AbortHandle

当调用此方法时,提供的 future 将立即开始在后台运行,即使你未在 JoinSet 上 await 任何东西也是如此。

§恐慌

如果在 Tokio 运行时之外调用,此方法会发生 panic。

源代码

pub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
where F: Future<Output = T> + Send + 'static, T: Send,

在所提供的运行时上生成提供的任务,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle

当调用此方法时,提供的 future 将立即开始在后台运行,即使你未在 JoinSet 上 await 任何东西也是如此。

源代码

pub fn spawn_local<F>(&mut self, task: F) -> AbortHandle
where F: Future<Output = T> + 'static,

在当前 LocalSetLocalRuntime 上生成提供的任务,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle

当调用此方法时,提供的 future 将立即开始在后台运行,即使你未在 JoinSet 上 await 任何东西也是如此。

§恐慌

如果在 LocalSetLocalRuntime 之外调用此方法,则会发生 panic。

源代码

pub fn spawn_local_on<F>( &mut self, task: F, local_set: &LocalSet, ) -> AbortHandle
where F: Future<Output = T> + 'static,

在所提供的 LocalSet 上生成提供的任务,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle

spawn_local 方法不同,此方法可用于在当前正在运行的 LocalSet 上生成本地任务。所提供的 future 将在下次启动 LocalSet 时开始运行。

源代码

pub fn spawn_blocking<F>(&mut self, f: F) -> AbortHandle
where F: FnOnce() -> T + Send + 'static, T: Send,

在阻塞线程池上生成阻塞代码,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle

§示例

生成多个阻塞任务并等待它们。

use tokio::task::JoinSet;

#[tokio::main]
async fn main() {
    let mut set = JoinSet::new();

    for i in 0..10 {
        set.spawn_blocking(move || { i });
    }

    let mut seen = [false; 10];
    while let Some(res) = set.join_next().await {
        let idx = res.unwrap();
        seen[idx] = true;
    }

    for i in 0..10 {
        assert!(seen[i]);
    }
}
§恐慌

如果在 Tokio 运行时之外调用,此方法会发生 panic。

源代码

pub fn spawn_blocking_on<F>(&mut self, f: F, handle: &Handle) -> AbortHandle
where F: FnOnce() -> T + Send + 'static, T: Send,

在所提供的运行时的阻塞线程池上生成阻塞代码,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle

源代码

pub async fn join_next(&mut self) -> Option<Result<T, JoinError>>

等待集合中某个任务完成并返回其输出。

如果集合为空,则返回 None

§Cancel Safety

此方法是可安全取消的。如果在 tokio::select! 语句中将 join_next 用作事件,并且其他某个分支先完成,则可以保证没有任务从此 JoinSet 中移除。

源代码

pub async fn join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>>

等待集合中某个任务完成,并返回其输出以及已完成任务的任务 ID

如果集合为空,则返回 None

当此方法返回错误时,失败任务的 ID 可以通过 JoinError::id 方法访问。

§Cancel Safety

此方法是可安全取消的。如果在 tokio::select! 语句中将 join_next_with_id 用作事件,并且其他某个分支先完成,则可以保证没有任务从此 JoinSet 中移除。

源代码

pub fn try_join_next(&mut self) -> Option<Result<T, JoinError>>

尝试连接集合中已完成的任务之一并返回其输出。

如果没有已完成的任务,或集合为空,则返回 None

源代码

pub fn try_join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>>

尝试连接集合中已完成的任务之一,并返回其输出以及已完成任务的任务 ID

如果没有已完成的任务,或集合为空,则返回 None

当此方法返回错误时,失败任务的 ID 可以通过 JoinError::id 方法访问。

源代码

pub async fn shutdown(&mut self)

中止所有任务并等待它们完成关闭。

调用此方法等效于先调用 abort_all,然后循环调用 join_next 直至其返回 None

此方法会忽略正在关闭的任务中的任何 panic。当此调用返回时,JoinSet 将为空。

源代码

pub async fn join_all(self) -> Vec<T>

等待此 JoinSet 中所有任务的完成,并返回一个包含其结果的向量。

结果将按其完成的顺序存储,而不是按其生成的顺序存储。这是一个便捷方法,等效于循环调用 join_next。如果 JoinSet 上的任何任务以 JoinError 失败,则对 join_all 的此次调用将 panic,并且 JoinSet 上所有剩余的任务都将被取消。要以其他方式处理错误,请手动循环调用 join_next

§示例

生成多个任务并 join_all 它们。

use tokio::task::JoinSet;
use std::time::Duration;

let mut set = JoinSet::new();

for i in 0..3 {
    set.spawn(async move {
        tokio::time::sleep(Duration::from_secs(3 - i)).await;
        i
    });
}

let output = set.join_all().await;
assert_eq!(output, vec![2, 1, 0]);

join_all 的等效实现,使用 join_next 和循环。

use tokio::task::JoinSet;
use std::panic;

let mut set = JoinSet::new();

for i in 0..3 {
    set.spawn(async move {i});
}

let mut output = Vec::new();
while let Some(res) = set.join_next().await{
    match res {
        Ok(t) => output.push(t),
        Err(err) if err.is_panic() => panic::resume_unwind(err.into_panic()),
        Err(err) => panic!("{err}"),
    }
}
assert_eq!(output.len(),3);
源代码

pub fn abort_all(&mut self)

中止此 JoinSet 上的所有任务。

这不会从 JoinSet 中移除任务。要等待任务完成取消,你应该循环调用 join_next 直至 JoinSet 为空。

源代码

pub fn detach_all(&mut self)

从此 JoinSet 中移除所有任务,但不会中止它们。

由此调用移除的任务将继续在后台运行,即使 JoinSet 已被 drop。

源代码

pub fn poll_join_next( &mut self, cx: &mut Context<'_>, ) -> Poll<Option<Result<T, JoinError>>>

轮询集合中是否有任务完成。

如果返回 Poll::Ready(Some(_)),则已完成的任务会从集合中移除。

当方法返回 Poll::Pending 时,所提供 Context 中的 Waker 会在 JoinSet 中有任务完成时被调度以接收唤醒。请注意,在多次调用 poll_join_next 时,只有传递给最近一次调用的 Context 中的 Waker 才会被调度以接收唤醒。

§Returns

此函数返回:

  • Poll::Pending if the JoinSet is not empty but there is no task whose output is available right now.
  • Poll::Ready(Some(Ok(value))) if one of the tasks in this JoinSet has completed. The value is the return value of one of the tasks that completed.
  • Poll::Ready(Some(Err(err))) if one of the tasks in this JoinSet has panicked or been aborted. The err is the JoinError from the panicked/aborted task.
  • Poll::Ready(None) if the JoinSet is empty.

请注意,即使其中一个任务已完成,此方法也可能返回 Poll::Pending。这可能发生在达到了协作预算上限时。

源代码

pub fn poll_join_next_with_id( &mut self, cx: &mut Context<'_>, ) -> Poll<Option<Result<(Id, T), JoinError>>>

轮询集合中是否有任务完成。

如果返回 Poll::Ready(Some(_)),则已完成的任务会从集合中移除。

当方法返回 Poll::Pending 时,所提供 Context 中的 Waker 会在 JoinSet 中有任务完成时被调度以接收唤醒。请注意,在多次调用 poll_join_next 时,只有传递给最近一次调用的 Context 中的 Waker 才会被调度以接收唤醒。

§Returns

此函数返回:

  • Poll::Pending if the JoinSet is not empty but there is no task whose output is available right now.
  • Poll::Ready(Some(Ok((id, value)))) if one of the tasks in this JoinSet has completed. The value is the return value of one of the tasks that completed, and id is the task ID of that task.
  • Poll::Ready(Some(Err(err))) if one of the tasks in this JoinSet has panicked or been aborted. The err is the JoinError from the panicked/aborted task.
  • Poll::Ready(None) if the JoinSet is empty.

请注意,即使其中一个任务已完成,此方法也可能返回 Poll::Pending。这可能发生在达到了协作预算上限时。

trait 实现§

源代码§

impl<T> Debug for JoinSet<T>

源代码§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

使用给定的格式化器格式化此值。 更多信息
源代码§

impl<T> 默认值 for JoinSet<T>

源代码§

fn default() -> Self

Returns the “default value” for a type. 更多信息
源代码§

impl<T> Drop for JoinSet<T>

源代码§

fn drop(&mut self)

执行此类型的析构函数。 更多信息
源代码§

impl<T, F> Extend<F> for JoinSet<T>
where F: Future<Output = T> + Send + 'static, T: Send + 'static,

使用来自迭代器的 future 扩展 JoinSet

这等效于对迭代器的每个元素调用 JoinSet::spawn

§示例

use tokio::task::JoinSet;

#[tokio::main]
async fn main() {
    let mut set: JoinSet<_> = (0..5).map(|i| async move { i }).collect();

    set.extend((5..10).map(|i| async move { i }));

    let mut seen = [false; 10];
    while let Some(res) = set.join_next().await {
        let idx = res.unwrap();
        seen[idx] = true;
    }

    for i in 0..10 {
        assert!(seen[i]);
    }
}
源代码§

fn extend<I>(&mut self, iter: I)
where I: IntoIterator<Item = F>,

Extends a collection with the contents of an iterator. 更多信息
源代码§

fn extend_one(&mut self, item: A)

🔬This is a nightly-only experimental API. (extend_one)
Extends a collection with exactly one element.
源代码§

fn extend_reserve(&mut self, additional: usize)

🔬This is a nightly-only experimental API. (extend_one)
Reserves capacity in a collection for the given number of additional elements. 更多信息
源代码§

impl<T, F> FromIterator<F> for JoinSet<T>
where F: Future<Output = T> + Send + 'static, T: Send + 'static,

将 future 的迭代器收集到 JoinSet 中。

这等效于对迭代器的每个元素调用 JoinSet::spawn

§示例

来自 JoinSet 文档的主要示例也可以使用 collect 来编写:

use tokio::task::JoinSet;

let mut set: JoinSet<_> = (0..10).map(|i| async move { i }).collect();

let mut seen = [false; 10];
while let Some(res) = set.join_next().await {
    let idx = res.unwrap();
    seen[idx] = true;
}

for i in 0..10 {
     assert!(seen[i]);
}
源代码§

fn from_iter<I: IntoIterator<Item = F>>(iter: I) -> Self

Creates a value from an iterator. 更多信息

自动 trait 实现§

§

impl<T> Freeze for JoinSet<T>

§

impl<T> RefUnwindSafe for JoinSet<T>

§

impl<T> Send for JoinSet<T>
where T: Send,

§

impl<T> Sync for JoinSet<T>
where T: Send,

§

impl<T> Unpin for JoinSet<T>

§

impl<T> UnsafeUnpin for JoinSet<T>

§

impl<T> UnwindSafe for JoinSet<T>

blanket 实现§

源代码§

impl<T> Any for T
where T: 'static + ?Sized,

源代码§

fn type_id(&self) -> TypeId

Gets the TypeId of self. 更多信息
源代码§

impl<T> Borrow<T> for T
where T: ?Sized,

源代码§

fn borrow(&self) -> &T

Immutably borrows from an owned value. 更多信息
源代码§

impl<T> BorrowMut<T> for T
where T: ?Sized,

源代码§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. 更多信息
源代码§

impl<T> From<T> for T

源代码§

fn from(t: T) -> T

原样返回参数。

源代码§

impl<T, U> Into<U> for T
where U: From<T>,

源代码§

fn into(self) -> U

调用 U::from(self)

也就是说,此转换是 From<T> for U 实现选择执行的操作。

源代码§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

源代码§

type Error = Infallible

转换出错时返回的类型。
源代码§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

执行转换。
源代码§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

源代码§

type Error = <U as TryFrom<T>>::Error

转换出错时返回的类型。
源代码§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

执行转换。