How about something like this?
use tokio::time::{sleep, Duration};
use rand::{thread_rng, Rng};
use tokio::task::JoinSet;
#[tokio::main]
async fn main() {
let max_concurrent = 2;
let ids: Vec<u64> = (1..=10).into_iter().collect();
let mut join_set = JoinSet::new();
for id in ids {
while join_set.len() >= max_concurrent {
join_set.join_next().await.unwrap().unwrap();
}
join_set.spawn(my_bg_task(id));
}
println!("DONE SPAWNING");
while let Some(output) = join_set.join_next().await {
output.unwrap();
}
println!("ALL DONE");
}
async fn my_bg_task(id: u64) {
let num: u64 = thread_rng().gen_range(10..200);
println!("START id: {} with {}ms", id, num);
sleep(Duration::from_millis(num)).await;
println!("STOP id: {}", id);
}