You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中进度反馈与取消机制的惯用实现方式

Rust中进度反馈与取消机制的惯用做法

一、取消机制

同步场景

Rust标准库没有内置类似C# CancellationToken的类型,但社区有成熟的实现方式:

  • 使用tokio::sync::CancellationToken(即使同步代码也能直接用,无需依赖异步runtime的其他功能),在函数的关键检查点调用ct.is_cancelled()判断是否需要终止执行,示例:
use tokio::sync::CancellationToken;

fn long_running_fun(actual_param: i32, ct: &CancellationToken) -> Result<(), ()> {
    for i in 0..100 {
        if ct.is_cancelled() {
            return Err(());
        }
        // 执行耗时操作
        std::thread::sleep(std::time::Duration::from_millis(10));
    }
    Ok(())
}
  • 若不想引入Tokio依赖,也可以用Arc<std::sync::atomic::AtomicBool>作为取消标记,每次迭代通过load(Ordering::Relaxed)检查状态。

注意:不要为了获取取消机制强行写异步代码,同步场景用同步的取消方案更符合Rust风格,异步是为IO密集或并发场景设计的,没必要硬套。

异步场景

Tokio等异步runtime支持通过JoinHandle::abort()直接取消任务,但如果需要函数内部主动响应取消(比如清理资源),推荐在函数参数中传入CancellationToken,或者用tokio::select!监听取消信号:

use tokio::sync::CancellationToken;
use tokio::time::{sleep, Duration};

async fn long_running_fun_async(actual_param: i32, ct: CancellationToken) -> Result<(), ()> {
    for i in 0..100 {
        tokio::select! {
            _ = sleep(Duration::from_millis(10)) => {},
            _ = ct.cancelled() => {
                // 执行资源清理
                return Err(());
            }
        }
    }
    Ok(())
}

二、进度反馈

Rust标准库没有类似C# IProgress<T>的标准trait,社区常用的实现方式有两种:

1. 传递回调函数

这是最直接的方式,函数接受一个可变闭包作为进度回调,内部在关键节点调用闭包传递进度:

fn long_running_fun_with_progress(actual_param: i32, mut progress: impl FnMut(f64)) {
    // 执行第一步,完成25%
    progress(0.25);
    // 执行第二步,完成50%
    progress(0.5);
    // 后续步骤...
    progress(1.0);
}

如果需要处理回调可能返回的错误,可以把闭包定义为impl FnMut(f64) -> Result<(), E>,函数内部处理错误并提前返回。

2. 使用通道传递进度

如果进度需要跨线程或异步任务传递,可以用std::sync::mpsc(同步)或tokio::sync::mpsc(异步)通道:

use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn long_running_fun_channel(actual_param: i32, sender: mpsc::Sender<f64>) -> Result<(), mpsc::SendError<f64>> {
    sender.send(0.0)?;
    thread::sleep(Duration::from_millis(100));
    sender.send(0.5)?;
    thread::sleep(Duration::from_millis(100));
    sender.send(1.0)?;
    Ok(())
}

// 调用方示例
let (sender, receiver) = mpsc::channel();
thread::spawn(move || {
    long_running_fun_channel(42, sender).unwrap();
});

for progress in receiver {
    println!("进度: {}%", progress * 100.0);
}

社区工具

如果是终端场景的进度展示,indicatif crate提供了开箱即用的进度条组件,无需自己实现进度传递逻辑。

总结

  • 同步耗时函数:用CancellationToken或原子布尔做取消,回调函数/通道做进度反馈;
  • 异步函数:结合runtime的取消机制,配合CancellationToken主动响应取消,进度反馈同样用回调或通道;
  • 避免为了取消强行异步,同步场景用同步方案更符合Rust惯用风格。

内容的提问来源于stack exchange,提问作者Dune

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 15:36:18