gpt4 book ai didi

rust - 如何使用带有异步的指示器显示总计数器栏?

转载 作者:行者123 更新时间:2023-12-03 11:36:12 29 4
gpt4 key购买 nike

我尝试使用 indicatif crate 显示多个子任务的进度条以及一个计算所有已完成任务的进度条。这是我的代码:

# Cargo.toml
[dependencies]
indicatif = "0.15.0"
tokio = { version = "1", features = ["full"] }
futures = "0.3"
//! main.rs
use std::time::Duration;
use futures::{StreamExt, stream::futures_unordered::FuturesUnordered};
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let m = MultiProgress::new();
let sty = ProgressStyle::default_bar()
.template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
.progress_chars("##-");
let total_pb = m.add(ProgressBar::new(3));
total_pb.set_style(sty.clone());
let mut futs = FuturesUnordered::new();
let durations = [15u64, 8, 3];
let mut pb_cnt = 0usize;
for &duration in durations.iter() {
let pb = m.insert(pb_cnt, ProgressBar::new(256));
pb_cnt += 1;
pb.set_style(sty.clone());
let total_pb = total_pb.clone();
let task = tokio::spawn(async move {
for i in 0i32..256 {
pb.set_message(&format!("item #{}", i + 1));
pb.inc(1);
tokio::time::sleep(Duration::from_millis(duration)).await;
}
pb.finish_with_message("done");
total_pb.inc(1);
});
futs.push(task);
}
while let Some(result) = futs.next().await {
result?;
}
total_pb.finish_with_message("done");
m.join()?;
// tokio::task::spawn_blocking(move || m.join().unwrap() ).await.unwrap();

Ok(())
}

total_pb 是计算所有已完成任务的栏。

问题是在所有工作完成之前控制台上不会出现进度条,只显示它们的最终状态。我尝试遵循 this issue 中的建议和 this issue , 但有几个问题:

  1. 我尝试像上面的代码一样插入 let m = tokio::task::spawn_blocking(move || m.join().unwrap()); 但它不起作用.
  2. total_pb 在所有任务完成之前不会完成,这意味着 m.join() 不能像第一个中建议的那样在每个生成的任务之后立即调用同步问题。

最佳答案

有不同的解决方案,您需要在事件阻塞线程上调用m.join()。要么你在你的主线程中做,所以你需要移动你的:

while let Some(result) = futs.next().await {
result?;
}

在其他地方,比如生成一个任务。

或者您生成一个阻塞线程并在最后等待它(可能是最好的)。所以就这样做:

let handle_m = tokio::task::spawn_blocking(move || m.join().unwrap()); // add this line
while let Some(result) = futs.next().await {
result?;
}
total_pb.finish_with_message("done");
handle_m.await?; // don't forget to await your handle

请注意,与您的尝试 #1 相反,您必须在等待结果之前生成阻塞线程...

有 2 个示例可以在将来帮助您 tokio.rs multi.rs .

关于rust - 如何使用带有异步的指示器显示总计数器栏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66220093/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com