pub fn spawn<T>(task: T) -> JoinHandle<T::Output>ⓘNotable traits for JoinHandle<T>impl<T> Future for JoinHandle<T> type Output = Result<T, JoinError>;
where
T: Future + Send + 'static,
T::Output: Send + 'static,
Expand description
Spawns a new asynchronous task, returning a
JoinHandle
for it.
Spawning a task enables the task to execute concurrently to other tasks. The
spawned task may execute on the current thread, or it may be sent to a
different thread to be executed. The specifics depend on the current
Runtime
configuration.
There is no guarantee that a spawned task will execute to completion. When a runtime is shutdown, all outstanding tasks are dropped, regardless of the lifecycle of that task.
This function must be called from the context of a Tokio runtime. Tasks running on
the Tokio runtime are always inside its context, but you can also enter the context
using the Handle::enter
method.
Examples
In this example, a server is started and spawn
is used to start a new task
that processes each received connection.
use tokio::net::{TcpListener, TcpStream};
use std::io;
async fn process(socket: TcpStream) {
// ...
}
#[tokio::main]
async fn main() -> io::Result<()> {
let mut 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
});
}
}
Panics
Panics if called from outside of the Tokio runtime.
Using !Send
values from a task
The task supplied to spawn
must implement Send
. However, it is
possible to use !Send
values from the task as long as they only
exist between calls to .await
.
For example, this will work:
use tokio::task;
use std::rc::Rc;
fn use_rc(rc: Rc<()>) {
// Do stuff w/ rc
}
#[tokio::main]
async fn main() {
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();
}
This will not work:
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();
}
Holding on to a !Send
value across calls to .await
will result in
an unfriendly compile error message similar to:
`[... some type ...]` cannot be sent between threads safely
or:
error[E0391]: cycle detected when processing `main`