Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asynchronous 如何使用指示符号显示异步状态下的总计数器条?_Asynchronous_Rust_Tokio - Fatal编程技术网

Asynchronous 如何使用指示符号显示异步状态下的总计数器条?

Asynchronous 如何使用指示符号显示异步状态下的总计数器条?,asynchronous,rust,tokio,Asynchronous,Rust,Tokio,我尝试使用“indicatif”包来显示子任务的多个进度条,同时显示一个进度条来统计所有已完成的任务。我的代码是异步的,使用tokio。以下是一个例子: 货舱 [package] name = "test-project" version = "0.1.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo

我尝试使用“indicatif”包来显示子任务的多个进度条,同时显示一个进度条来统计所有已完成的任务。我的代码是异步的,使用tokio。以下是一个例子:

货舱

[package]
name = "test-project"
version = "0.1.0"
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
indicatif = "0.15.0"
tokio = { version = "1", features = ["full"] }
futures = "0.3"
src/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(())
}
使用std::time::Duration;
使用期货:{StreamExt,stream::futures\u unordered::FuturesUnordered};
使用指示符:{MultiProgress,ProgressBar,ProgressStyle};
#[tokio::main]
异步fn main()->结果{
设m=MultiProgress::new();
让sty=ProgressStyle::default\u bar()
.template(“[{eassed_precise}]{bar:40.cyan/blue}{pos:>7}/{len:7}{msg}”)
.progress_chars(“##-”);
让total_pb=m.add(ProgressBar::new(3));
total_pb.set_样式(sty.clone());
让mut futs=FuturesUnordered::new();
设持续时间=[15u64,8,3];
让mut pb_cnt=0使用;
以持续时间为单位的持续时间(&D)。iter(){
设pb=m.insert(pb_cnt,ProgressBar::new(256));
pb_cnt+=1;
pb.set_样式(sty.clone());
让total_pb=total_pb.clone();
让task=tokio::spawn(异步移动{
对于0i32..256中的i{
pb.set_消息(&格式!(“项{}”,i+1));
pb.inc(1);
tokio::time::sleep(持续时间::from_millis(持续时间))。等待;
}
pb.用消息(“完成”)完成任务;
道达尔私人有限公司(1);
});
未来推动(任务);
}
而让一些(结果)=futs.next()等待{
结果?;
}
用消息(“完成”)完成的总容量;
m、 join()?;
//tokio::task::spawn|u阻塞(move | | m.join().unwrap()).wait.unwrap();
好(())
}
total_pb
是计算所有已完成任务的条形图

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

  • 我尝试插入
    让m=tokio::task::spawn|u阻塞(move | | m.join().unwrap())与上面的代码相同,但不起作用
    
  • total_pb
    在所有任务完成之前不会完成,这意味着不能在每个生成的任务之后立即调用
    m.join()
    ,作为issue1中建议的同步

  • 如果相关,我使用Windows 10。

    有不同的解决方案,您需要在活动阻止线程上调用
    m.join()
    。您可以在主线程中执行此操作,因此需要移动:

    while让一些(结果)=futs.next().等待{
    结果?;
    }
    
    在其他地方,例如生成任务

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

    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
    
    请注意,与您的try#1相反,您必须在等待结果之前生成阻塞线程

    有两个例子可以在将来帮助您