Werken met futures en taken
Krijg inzicht in de trait `Future` en ontdek hoe taken binnen een asynchrone runtime-omgeving worden gepland en beheerd.
Werken met futures en taken is een gratis Leer programmeren met Rust-les op CoddyKit. Dit is les 3 van 3. Je kunt 3 lessen uit dit leerpad gratis volledig lezen — daarna ontgrendelt CoddyKit PRO alle lessen, plus praktische oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. Deze les maakt deel uit van het leertraject Leer programmeren met Rust. Je voortgang wordt gesynchroniseerd op het web en in de CoddyKit-app. De cursus Leer programmeren met Rust bevat in totaal 3 lessen.
Wat is een Rust-Future?
In asynchroon Rust is een Future een trait die een asynchrone berekening vertegenwoordigt die op een bepaald moment kan worden voltooid. Zie het als een belofte voor een waarde die nog niet gereed is.
- Het is een fundamentele bouwsteen van asynchroon Rust.
async fns in Rust retourneren in werkelijkheid een anoniem type dat deFuture-trait implementeert.- De waarde wordt niet onmiddellijk berekend; dat gebeurt wanneer een uitvoerder de
Future"pollt".
Hoe Futures voortgang maken
Een Future wordt niet vanzelf uitgevoerd. Een uitvoerder (zoals de Tokio-runtime) "pollt" deze herhaaldelijk om te controleren of er voortgang is gemaakt of de uitvoering is voltooid.
- Bij het pollen retourneert een
FuturePoll::Pending(nog niet voltooid) ofPoll::Ready(T)(voltooid, dit is het resultaat). - Bij
Pendingweet de uitvoerder dat hij de Future later opnieuw moet pollen wanneer er iets relevants gebeurt (bijvoorbeeld wanneer I/O is voltooid). - Dankzij dit pollmechanisme kunnen veel asynchrone bewerkingen gelijktijdig op één thread worden uitgevoerd.
Je asynchrone code is een Future
Wanneer je een async fn schrijft, zet Rust deze om in een toestandsmachine die de Future-trait implementeert. De daadwerkelijke berekening begint pas wanneer de geretourneerde Future wordt gepolld.
Bekijk een eenvoudige async-functie. Deze wordt pas uitgevoerd wanneer een uitvoerder erop wacht.
async fn say_hello() -> String {
"Hello from a Future!".to_string()
}
#[tokio::main]
async fn main() {
let future = say_hello(); // This doesn't run the function yet!
println!("Future created, but not awaited.");
// To run it, an executor needs to poll it, often via .await
// let result = future.await;
// println!("{}", result);
}Futures worden taken
Een Future is de definitie van een asynchrone berekening, terwijl een taak een actieve instantie van die Future is die door een uitvoerder naar voltooiing wordt gebracht.
- Wanneer je een uitvoerder (zoals Tokio) opdraagt een
Futureuit te voeren, verpakt deze de Future in een taak. - De uitvoerder beheert deze taak vervolgens en poolt deze telkens wanneer de taak klaar is om voortgang te maken.
- Taken zijn de werkeenheden die de asynchrone runtime inplant en gelijktijdig uitvoert.
Taken starten voor gelijktijdigheid
Als je een Future gelijktijdig met andere code wilt uitvoeren, start je deze op de Tokio-runtime. Hierdoor wordt een nieuwe taak gemaakt die door de runtime wordt beheerd.
De functie tokio::spawn neemt een Future aan en retourneert een JoinHandle. Daarmee kun je wachten tot de taak is voltooid en het resultaat ervan ophalen.
async fn perform_task(id: u8) -> String {
tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
format!("Task {} finished!", id)
}
#[tokio::main]
async fn main() {
println!("Main started.");
let handle = tokio::spawn(async {
perform_task(1).await
});
println!("Task 1 spawned.");
// We will await 'handle' in the next scene to get the result.
// let result = handle.await.unwrap();
// println!("{}", result);
}Resultaten van taken ophalen
De JoinHandle die door tokio::spawn wordt geretourneerd, is zelf een Future. Je kunt met .await op deze handle wachten totdat de gestarte taak is voltooid en de geretourneerde waarde ervan ophalen.
Als de gestarte taak in paniek raakt, retourneert het wachten op de JoinHandle een fout.
async fn perform_task(id: u8) -> String {
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
format!("Task {} finished!", id)
}
#[tokio::main]
async fn main() {
println!("Main started.");
let handle = tokio::spawn(async {
perform_task(1).await
});
println!("Task 1 spawned.");
let result = handle.await.unwrap(); // Await the handle to get the result
println!("{}", result);
println!("Main finished.");
}Meerdere gelijktijdige taken
De kracht van taken en tokio::spawn komt echt tot zijn recht wanneer je meerdere bewerkingen gelijktijdig uitvoert. De Tokio-runtime schakelt efficiënt tussen taken zodra deze gereed zijn.
Hierdoor kan je programma aan veel dingen tegelijk voortgang boeken zonder te blokkeren, zelfs op één thread.
async fn long_task(id: u8) -> String {
tokio::time::sleep(tokio::time::Duration::from_millis(100 + id as u64 * 50)).await;
format!("Long task {} done!", id)
}
#[tokio::main]
async fn main() {
println!("Main started.");
let handle1 = tokio::spawn(long_task(1));
let handle2 = tokio::spawn(long_task(2));
println!("Both tasks spawned.");
let result1 = handle1.await.unwrap();
let result2 = handle2.await.unwrap();
println!("{}\n{}", result1, result2);
println!("Main finished.");
}Op alles wachten met join!
Wanneer je wilt wachten totdat meerdere Futures tegelijk zijn voltooid, is tokio::join! een handige macro. Deze wacht gelijktijdig op alle opgegeven futures en retourneert hun resultaten als een tuple.
Dit lijkt op afzonderlijk wachten op elke handle, maar is vaak beknopter voor een vast aantal futures.
async fn fetch_data(source: &str) -> String {
tokio::time::sleep(tokio::time::Duration::from_millis(50)).await;
format!("Data from {}", source)
}
#[tokio::main]
async fn main() {
println!("Starting data fetches...");
let (data_a, data_b) = tokio::join!(
fetch_data("Server A"),
fetch_data("Database B")
);
println!("Fetched: {}\nFetched: {}", data_a, data_b);
println!("All fetches complete.");
}Fouten in taken afhandelen
Asynchrone bewerkingen kunnen mislukken, net als synchrone bewerkingen. Het is gebruikelijk dat Futures een type Result retourneren dat succes of mislukking aangeeft.
Wanneer je op een JoinHandle wacht, moet je bedenken dat het resultaat in nog een Result is verpakt, omdat de taak zelf in paniek kan raken. Je ziet vaak handle.await? (binnen een async fn die Result retourneert) of handle.await.unwrap() / .expect().
async fn might_fail(should_fail: bool) -> Result<String, &'static str> {
tokio::time::sleep(tokio::time::Duration::from_millis(30)).await;
if should_fail {
Err("Oops, something went wrong!")
} else {
Ok("Operation successful!".to_string())
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let handle_ok = tokio::spawn(might_fail(false));
let handle_err = tokio::spawn(might_fail(true));
let result_ok = handle_ok.await??; // Await handle, then await inner Result
println!("{}", result_ok);
match handle_err.await? { // Await handle, then handle inner Result
Ok(val) => println!("{}", val),
Err(e) => eprintln!("Error: {}", e),
}
Ok(())
}Futures en taken begrijpen
Je hebt geleerd over Futures als berekeningen en taken als de uitvoeringsinstanties daarvan. Welke uitspraak over tokio::spawn en JoinHandle is juist?
Samenvatting: Futures en taken
Goed gedaan! Je begrijpt nu de belangrijkste concepten van Futures en taken in het asynchrone ecosysteem van Rust:
- Een
Futureis een trait die een asynchrone berekening vertegenwoordigt die uiteindelijk een waarde oplevert. async fns worden gecompileerd naar typen die deFuture-trait implementeren.- Een taak is een instantie van een
Futuredie een uitvoerder (zoals Tokio) actief beheert en poolt. - Met
tokio::spawnmaak je een nieuwe taak, waarbij eenJoinHandlewordt geretourneerd. - Je wacht met
.awaitop eenJoinHandleom het resultaat van een gestarte taak op te halen.
Deze bouwstenen zijn essentieel voor het schrijven van efficiënte, niet-blokkerende Rust-toepassingen!
Leer Rust met een AI-tutor — gratis
Schrijf echte code en voer die uit in je browser, krijg direct hulp van een AI-tutor die 24/7 beschikbaar is en ga verder waar je gebleven bent op het web of in de app.
- Cursussen
- 39
- Lessen
- 144
Veelgestelde vragen
Is de les “Werken met futures en taken” gratis?
Ja — je kunt hier op het web alle 3 lessen van het leerpad Leer programmeren met Rust, waaronder “Werken met futures en taken”, gratis volledig lezen. Daarna ontgrendelt CoddyKit PRO alle lessen, plus interactieve oefeningen met een ingebouwde code-editor en een AI-tutor die 24/7 beschikbaar is. De cursus Leer programmeren met Rust bevat in totaal 3 lessen.
Wat leer ik in “Werken met futures en taken”?
Krijg inzicht in de trait `Future` en ontdek hoe taken binnen een asynchrone runtime-omgeving worden gepland en beheerd. Je oefent met Leer programmeren met Rust door code rechtstreeks in de browser uit te voeren. Een AI-begeleider die 24/7 beschikbaar is beantwoordt je vragen terwijl je de les doorwerkt.
Heb ik ervaring nodig om met Leer programmeren met Rust te beginnen?
Ervaring vooraf is niet nodig. Leer programmeren met Rust op CoddyKit is opgebouwd voor beginners tot gevorderden, zodat je hier of bij het begin kunt starten en in je eigen tempo kunt leren. Dit is les 3 van 3.
Hoe lang duurt de les “Werken met futures en taken”?
De meeste lessen van CoddyKit duren ongeveer 5–10 minuten. Elke les is kort en interactief, zodat je gestaag vooruitgaat en op het web en in de app precies verdergaat waar je was gebleven.
Kan ik code schrijven en uitvoeren in deze les over Leer programmeren met Rust?
Ja. Elke les over Leer programmeren met Rust bevat een ingebouwde code-editor, zodat je rechtstreeks in je browser echte code kunt schrijven en uitvoeren en direct feedback van AI krijgt — lokale installatie is niet nodig.
Alle lessen in deze cursus
- Inleiding tot async/await
- Asynchrone applicaties bouwen met Tokio
- Werken met futures en taken