pub struct JoinSet<T> { /* private fields */ }展开描述
在 Tokio runtime 上生成的若干任务的集合。
JoinSet 可用于等待集合中部分或全部任务的完成。该集合是无序的,任务将按照完成的顺序返回。
所有任务必须具有相同的返回类型 T。
当 JoinSet 被丢弃时,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。有关更多信息,请参阅 task ID 文档。
实现§
Source§impl<T: 'static> JoinSet<T>
impl<T: 'static> JoinSet<T>
Sourcepub fn spawn<F>(&mut self, task: F) -> AbortHandle
pub fn spawn<F>(&mut self, task: F) -> AbortHandle
将提供的任务派生到 JoinSet 上,返回一个 AbortHandle,可用于远程取消该任务。
提供的 future 会在调用此方法时立即开始在后台运行,即使你没有在该 JoinSet 上 await 任何东西。
§Panics
如果在 Tokio runtime 之外调用此方法会 panic。
Sourcepub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
pub fn spawn_on<F>(&mut self, task: F, handle: &Handle) -> AbortHandle
将提供的任务派生到给定的 runtime 上并存储到此 JoinSet,返回一个 AbortHandle,可用于远程取消该任务。
提供的 future 会在调用此方法时立即开始在后台运行,即使你没有在该 JoinSet 上 await 任何东西。
Sourcepub 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 任何东西。
§Panics
如果在 LocalSet 或 LocalRuntime 之外调用此方法会 panic。
Sourcepub 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 下次启动时开始运行。
Sourcepub 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]);
}
}§Panics
如果在 Tokio runtime 之外调用此方法会 panic。
Sourcepub 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
将阻塞代码派生到给定 runtime 的阻塞线程池上并存储到此 JoinSet,返回一个 AbortHandle,可用于远程取消该任务。
Sourcepub async fn join_next(&mut self) -> Option<Result<T, JoinError>>
pub async fn join_next(&mut self) -> Option<Result<T, JoinError>>
等待集合中的某个任务完成,并返回其输出。
如果集合为空则返回 None。
§Cancel Safety
此方法是 cancel safe 的。如果 join_next 在 tokio::select! 语句中作为事件且其他分支先完成,可以保证不会有任务从此 JoinSet 中被移除。
Sourcepub 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>>
等待集合中的某个任务完成,并返回其输出以及完成任务对应的 task ID。
如果集合为空则返回 None。
当此方法返回错误时,可通过 JoinError::id 方法访问失败任务的 ID。
§Cancel Safety
此方法是 cancel safe 的。如果 join_next_with_id 在 tokio::select! 语句中作为事件且其他分支先完成,可以保证不会有任务从此 JoinSet 中被移除。
Sourcepub fn try_join_next(&mut self) -> Option<Result<T, JoinError>>
pub fn try_join_next(&mut self) -> Option<Result<T, JoinError>>
尝试加入集合中已完成的任务之一,并返回其输出。
如果没有已完成的任务,或集合为空,则返回 None。
Sourcepub 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>>
尝试加入集合中已完成的任务之一,返回其输出以及完成任务对应的 task ID。
如果没有已完成的任务,或集合为空,则返回 None。
当此方法返回错误时,可通过 JoinError::id 方法访问失败任务的 ID。
Sourcepub async fn join_all(self) -> Vec<T>
pub async fn join_all(self) -> Vec<T>
等待此 JoinSet 中所有任务完成,返回一个包含其结果的 vector。
结果将按照任务完成的顺序(而非派生的顺序)存储。这是一个便捷方法,等价于循环调用 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_next 和循环实现等效的 join_all。
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);Sourcepub fn abort_all(&mut self)
pub fn abort_all(&mut self)
终止此 JoinSet 上的所有任务。
这不会从 JoinSet 中移除任务。要等待任务完成取消,你应该循环调用 join_next,直到 JoinSet 为空。
Sourcepub fn detach_all(&mut self)
pub fn detach_all(&mut self)
从 JoinSet 中移除所有任务而不终止它们。
被此调用移除的任务将在后台继续运行,即使 JoinSet 被丢弃。
Sourcepub 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 中的任务完成时接收 wakeup。请注意,多次调用 poll_join_next 时,只有最近一次调用所传入 Context 中的 Waker 会被调度接收 wakeup。
§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。当达到 协作预算 上限时,就会发生这种情况。
Sourcepub 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 中的任务完成时接收 wakeup。请注意,多次调用 poll_join_next 时,只有最近一次调用所传入 Context 中的 Waker 会被调度接收 wakeup。
§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 实现§
Source§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]);
}
}Source§fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = F>,
fn extend<I>(&mut self, iter: I)where
I: IntoIterator<Item = F>,
Source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one)Source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one)Source§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]);
}