pub trait AsyncExt<Marker> {
type System: System;
// Required method
fn detach(self) -> Self::System;
}Expand description
Adds .detach() to a function/closure whose
parameters are valid SystemParams and which returns a
Future<Output = ()> + Send + 'static, registering it as a system.
Each tick, the wrapped function is called synchronously like any other
system — its SystemParams (Res, Query, …) are fetched and
borrowed exactly as usual — but instead of doing work directly, it
builds and returns a future (typically an async move { .. } block that
has cloned or copied out whatever owned data it needs from those
borrows). The scheduler then hands that future to
BackgroundTasks::spawn_async
and moves on immediately — the future runs to completion on a worker
thread, off the main loop, with no access to the World/Resources
(which is exactly why it has to be 'static: nothing borrowed from this
tick is valid once the future outlives it).
A real async fn can’t be used directly as the wrapped function here:
its returned future borrows every one of its parameters by construction,
so it’s never 'static on its own. Extract the owned pieces you need in
the ordinary (synchronous) function body, then move only those into the
async move block you return.
Fire-and-forget: nothing delivers the future’s result back
automatically, and a system that unconditionally detaches a new future
every tick will spawn a new one every tick. If you need the result, or
want to send only once, call BackgroundTasks::spawn_async yourself
inside an ordinary system (guarding with Local<bool> or
OnceExt::once as needed) and poll the returned
TaskHandle — same pattern already used
for the async GPU backend init.
fn load_level(tasks: Res<BackgroundTasks>) -> impl Future<Output = ()> + Send + 'static {
let tasks = tasks.clone();
async move {
let bytes = std::fs::read("level.bin").unwrap();
// ... process `bytes`, maybe tasks.spawn_blocking(...) more work ...
}
}
app.add_system(SystemStage::Update, load_level.detach());Required Associated Types§
Required Methods§
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".