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: 'static> JoinSet<T>
impl<T: 'static> JoinSet<T>
源代码pub fn spawn<F>(&mut self, task: F) -> AbortHandle
pub fn spawn<F>(&mut self, task: F) -> AbortHandle
在 JoinSet 上生成提供的任务,返回一个可用于远程取消任务的 AbortHandle。
当调用此方法时,提供的 future 将立即开始在后台运行,即使你未在 JoinSet 上 await 任何东西也是如此。
§恐慌
如果在 Tokio 运行时之外调用,此方法会发生 panic。
源代码pub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
pub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
在所提供的运行时上生成提供的任务,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle。
当调用此方法时,提供的 future 将立即开始在后台运行,即使你未在 JoinSet 上 await 任何东西也是如此。
源代码pub fn spawn_local<F>(&mut self, task: F) -> AbortHandlewhere
F: Future<Output = T> + 'static,
pub fn spawn_local<F>(&mut self, task: F) -> AbortHandlewhere
F: Future<Output = T> + 'static,
在当前 LocalSet 或 LocalRuntime 上生成提供的任务,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle。
当调用此方法时,提供的 future 将立即开始在后台运行,即使你未在 JoinSet 上 await 任何东西也是如此。
§恐慌
如果在 LocalSet 或 LocalRuntime 之外调用此方法,则会发生 panic。
源代码pub fn spawn_local_on<F>(
&mut self,
task: F,
local_set: &LocalSet,
) -> AbortHandlewhere
F: Future<Output = T> + 'static,
pub fn spawn_local_on<F>(
&mut self,
task: F,
local_set: &LocalSet,
) -> AbortHandlewhere
F: Future<Output = T> + 'static,
在所提供的 LocalSet 上生成提供的任务,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle。
与 spawn_local 方法不同,此方法可用于在不当前正在运行的 LocalSet 上生成本地任务。所提供的 future 将在下次启动 LocalSet 时开始运行。
源代码pub fn spawn_blocking<F>(&mut self, f: F) -> AbortHandle
pub fn spawn_blocking<F>(&mut self, f: F) -> AbortHandle
在阻塞线程池上生成阻塞代码,并将其存储在此 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
pub fn spawn_blocking_on<F>(&mut self, f: F, handle: &Handle) -> AbortHandle
在所提供的运行时的阻塞线程池上生成阻塞代码,并将其存储在此 JoinSet 中,返回一个可用于远程取消任务的 AbortHandle。
源代码pub async fn join_next(&mut self) -> Option<Result<T, JoinError>>
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>>
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>>
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>>
pub fn try_join_next_with_id(&mut self) -> Option<Result<(Id, T), JoinError>>
尝试连接集合中已完成的任务之一,并返回其输出以及已完成任务的任务 ID。
如果没有已完成的任务,或集合为空,则返回 None。
当此方法返回错误时,失败任务的 ID 可以通过 JoinError::id 方法访问。
源代码pub async fn join_all(self) -> Vec<T>
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)
pub fn abort_all(&mut self)
中止此 JoinSet 上的所有任务。
这不会从 JoinSet 中移除任务。要等待任务完成取消,你应该循环调用 join_next 直至 JoinSet 为空。
源代码pub fn detach_all(&mut self)
pub fn detach_all(&mut self)
从此 JoinSet 中移除所有任务,但不会中止它们。
由此调用移除的任务将继续在后台运行,即使 JoinSet 已被 drop。
源代码pub fn poll_join_next(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Option<Result<T, JoinError>>>
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::Pendingif theJoinSetis not empty but there is no task whose output is available right now.Poll::Ready(Some(Ok(value)))if one of the tasks in thisJoinSethas completed. Thevalueis the return value of one of the tasks that completed.Poll::Ready(Some(Err(err)))if one of the tasks in thisJoinSethas panicked or been aborted. Theerris theJoinErrorfrom the panicked/aborted task.Poll::Ready(None)if theJoinSetis empty.
请注意,即使其中一个任务已完成,此方法也可能返回 Poll::Pending。这可能发生在达到了协作预算上限时。
源代码pub fn poll_join_next_with_id(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Option<Result<(Id, T), JoinError>>>
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::Pendingif theJoinSetis 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 thisJoinSethas completed. Thevalueis the return value of one of the tasks that completed, andidis the task ID of that task.Poll::Ready(Some(Err(err)))if one of the tasks in thisJoinSethas panicked or been aborted. Theerris theJoinErrorfrom the panicked/aborted task.Poll::Ready(None)if theJoinSetis empty.
请注意,即使其中一个任务已完成,此方法也可能返回 Poll::Pending。这可能发生在达到了协作预算上限时。
trait 实现§
源代码§impl<T, F> Extend<F> for JoinSet<T>
使用来自迭代器的 future 扩展 JoinSet。
impl<T, F> Extend<F> for JoinSet<T>
使用来自迭代器的 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>,
fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = F>,
源代码§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)源代码§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)源代码§impl<T, F> FromIterator<F> for JoinSet<T>
将 future 的迭代器收集到 JoinSet 中。
impl<T, F> FromIterator<F> for JoinSet<T>
将 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]);
}