Summary - Tokio
- Rust course
- Advanced
- Lesson 12/81
- 5 min
Race two async tasks by combining spawn and select!.
Tokio summary
Tokio provides a runtime for async Rust: the #[tokio::main] entry, light tasks with tokio::spawn, communication between tasks with tokio::sync (mpsc, oneshot, Mutex), async I/O with tokio::fs/net, and racing and cancellation with select!/timeout. Golden rule: don't make blocking calls in an async task; use spawn_blocking if you must.
The worker pattern
A copy of the sender is given to each worker; once the original sender is dropped, the receiver's iterator ends when all workers finish:
let (tx, rx) = mpsc::channel();
for id in 0..4 {
let tx = tx.clone();
thread::spawn(move || tx.send(id * 10).unwrap());
}
drop(tx); // drop the original sender
let sonuclar: Vec<i32> = rx.iter().collect(); // 4 results, order undefinedSince the order of results is undefined, only order-independent summaries (sum, count) can be printed safely.
Practice Collect from workers
Start four worker threads; let each send id * 10 to the same channel. Drop the original sender, collect the results with rx.iter() and print them as N sonuç, toplam X.
Starter code
use std::sync::mpsc;
use std::thread;
fn main() {
// buraya yaz
}Sample solution
use std::sync::mpsc;
use std::thread;
fn main() {
let (tx, rx) = mpsc::channel();
for id in 0..4 {
let tx = tx.clone();
thread::spawn(move || tx.send(id * 10).unwrap());
}
drop(tx);
let sonuclar: Vec<i32> = rx.iter().collect();
let toplam: i32 = sonuclar.iter().sum();
println!("{} sonuç, toplam {}", sonuclar.len(), toplam);
}Expected output
4 sonuç, toplam 60
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Which pattern fits gathering the results of many workers in one place?
- A cloned sender for each worker (tx.clone()), a single receiver Correct answer
- A separate global for each worker
- Each worker writes to a file
- It isn't possible
Explanation: mpsc: many producers, single consumer. Once all senders are dropped, the receiver's loop ends by itself.
2 Drop the original sender
for id in 0..4 {
let tx = tx.clone();
thread::spawn(move || tx.send(id).unwrap());
}
____(tx);
let hepsi: Vec<i32> = rx.iter().collect();
for id in 0..4 {
let tx = tx.clone();
thread::spawn(move || tx.send(id).unwrap());
}
drop(tx);
let hepsi: Vec<i32> = rx.iter().collect();
Explanation: If the original tx isn't dropped, rx.iter() never ends.
3 Group summary
| Term | Meaning |
|---|---|
#[tokio::main] |
Runtime entry |
tokio::spawn |
Task |
select! |
First to finish wins |
spawn_blocking |
Blocking work |