#thread #parallel

status_executor

在某个上下文(线程)上运行您的任务,并获取状态信息

1 个不稳定版本

0.1.0 2023年12月20日

#692 in 并发

MIT/Apache

19KB
250

执行长时间运行的计算任务,可选地返回状态信息

示例用法

    use status_executor::{StatusExecutor, StatusSender, StdContext};
    // status data need to be Send + 'static and also implement Clone
    #[derive(Debug,Clone)]
    struct MyStatus {
        progress: i32,
        msg: String,
    }
    // lets some heavy work instead of this
    let e = StatusExecutor::new(StdContext::default(), |s| {
        let mut p = 0;
        while p < 100 {
            std::thread::sleep(std::time::Duration::from_secs_f32(0.4));
            s.send(MyStatus {
                progress: p,
                msg: "Working...".to_string(),
            });
            p += 15;
        }
        // post that we are done!
        s.send(MyStatus {
            progress: p,
            msg: "Done!".to_string(),
        });
        p
    });
    // your gui or whatever might grab the most recent (or none, if none is available) status
    while !e.is_done() {
        match e.status() {
            Some(s) => println!("{} - currently at {}", s.msg, s.progress),
            None => std::thread::yield_now(),
        }
    }
    // the most recent status is also saved even if nothing new is produced.
    match e.latest_status() {
         Some(s) => println!("{} - last at {}", s.msg, s.progress),
         None => {
             assert!(false, "We produced *at least* one status, this should ont happen");
         }
    }
    // result is an Option<Arc<T>> because otherwise you would have to either move it out of the internal state
    // or track the locking used for the internal state
    //let res = e.result().expect("function returned is_done() == true, this should exist now");
    // you can, however just take the result as well, consuming the executor.
    let res = e.take_result();
    assert_eq!(res,Some(105));

动机

有时需要卸载计算任务。异步处理不好这类任务,而 tokio 等库提供了特定的上下文和线程池来运行计算任务。而且,截至撰写本笔记时,在异步上下文之外,实际上并没有真正能够简化这类一次性启动、持续很长时间的任务的方法。

status_executor 为此任务提供了两个 Structs - ExecutorStatusExecutor。Executor 本身不过是一个夸大的 join handle。使用它变得有趣,如果你启用了 rayon 功能。然后你可以使用 Executor::new,而不是使用 RayonContext,这将在 rayons 的全局池中生成工作。

StatusExecutor 是命名的部分。比如说,你有一个 GUI 应用程序,你在后台进行 繁重 的处理。用户可能对当前状态感兴趣(毕竟,这可能需要 20 分钟左右)。显然的解决方案是一个通道。然而,快速编写这个可能有点繁琐。因此,StatusExecutor 是一个用于此目的的小助手。

恐慌行为

在执行器中运行的线程可能会恐慌,如果使用了 rayon 功能,rayon 确实有一个恐慌处理器,这通常会引发中止(除非你修改线程池的恐慌处理器)。作为镜像,StdContext 将终止进程。使用 RayonGlobalContextRayonContext 将使用设置的恐慌处理器,这可能会是另一个恐慌。

依赖项

~0–265KB