pub fn spawn<F>(future: F) -> JoinHandle<F::Output> ⓘ展开描述
生成一个新的异步 task,返回一个 JoinHandle。
当调用 spawn 时,
所提供的 future
将立即开始在后台运行,
即使你没有等待返回的
JoinHandle。
派生一个任务
使该任务能够与其他任务并发执行。
派生的任务可以在当前线程上执行,
也可以被发送到其他线程执行。
具体细节取决于当前的
Runtime
配置。
在
正在运行的运行时中,
任务将立即在后台开始。
在阻塞的运行时中,
用户必须向前驱动运行时
(例如,通过调用
Runtime::block_on)。
可以保证 spawn 不会同步轮询正在派生的任务。 这意味着在持有锁的同时调用 spawn 不会带来与 派生任务死锁的风险。
无法保证派生的任务将执行到完成。 当运行时关闭时,所有未完成的任务都 将被丢弃,无论该任务的生命周期如何。
This function must be called from the context of a Tokio 运行时。 Tasks running on
the Tokio runtime are always inside its context, but you can also enter the context
using the Runtime::enter method.
§示例
在此示例中,
启动了一个服务器,
并使用 spawn
启动一个新任务
来处理每个接收到的连接。
use tokio::net::{TcpListener, TcpStream};
use std::io;
async fn process(socket: TcpStream) {
// ...
}
#[tokio::main]
async fn main() -> io::Result<()> {
let listener = TcpListener::bind("127.0.0.1:8080").await?;
loop {
let (socket, _) = listener.accept().await?;
tokio::spawn(async move {
// Process each socket concurrently.
process(socket).await
});
}
}要并行运行多个任务并接收它们的结果, 可以将 join 句柄存储在一个 vector 中。
async fn my_background_op(id: i32) -> String {
let s = format!("Starting background task {}.", id);
println!("{}", s);
s
}
let ops = vec![1, 2, 3];
let mut tasks = Vec::with_capacity(ops.len());
for op in ops {
// This call will make them start running in the background
// immediately.
tasks.push(tokio::spawn(my_background_op(op)));
}
let mut outputs = Vec::with_capacity(tasks.len());
for task in tasks {
outputs.push(task.await.unwrap());
}
println!("{:?}", outputs);本示例按任务启动的顺序
将任务推送到 outputs 中。
如果你不关心输出的顺序,
那么
也可以使用
JoinSet。
§Panics
Panics if called from outside of the Tokio 运行时。
§Using !Send values from a task
提供给 spawn 的任务
必须实现 Send。
但是,
只要它们仅存在于
对 .await 的调用之间,
就可以使用
!Send 值。
例如,下面的代码可以工作:
use tokio::task;
use std::rc::Rc;
fn use_rc(rc: Rc<()>) {
// Do stuff w/ rc
}
tokio::spawn(async {
// Force the `Rc` to stay in a scope with no `.await`
{
let rc = Rc::new(());
use_rc(rc.clone());
}
task::yield_now().await;
}).await.unwrap();这是行不通的:
use tokio::task;
use std::rc::Rc;
fn use_rc(rc: Rc<()>) {
// Do stuff w/ rc
}
#[tokio::main]
async fn main() {
tokio::spawn(async {
let rc = Rc::new(());
task::yield_now().await;
use_rc(rc.clone());
}).await.unwrap();
}在 .await 调用之间
保留一个 !Send 值
将导致一个不友好的编译错误消息,
类似于:
`[... some type ...]` cannot be sent between threads safelyor:
error[E0391]: cycle detected when processing `main`