1 个不稳定版本
0.1.0 | 2023年12月20日 |
---|
#692 in 并发
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 - Executor
和 StatusExecutor
。Executor 本身不过是一个夸大的 join handle。使用它变得有趣,如果你启用了 rayon 功能。然后你可以使用 Executor::new
,而不是使用 RayonContext
,这将在 rayons 的全局池中生成工作。
StatusExecutor
是命名的部分。比如说,你有一个 GUI 应用程序,你在后台进行 繁重 的处理。用户可能对当前状态感兴趣(毕竟,这可能需要 20 分钟左右)。显然的解决方案是一个通道。然而,快速编写这个可能有点繁琐。因此,StatusExecutor
是一个用于此目的的小助手。
恐慌行为
在执行器中运行的线程可能会恐慌,如果使用了 rayon 功能,rayon 确实有一个恐慌处理器,这通常会引发中止(除非你修改线程池的恐慌处理器)。作为镜像,StdContext
将终止进程。使用 RayonGlobalContext
或 RayonContext
将使用设置的恐慌处理器,这可能会是另一个恐慌。
依赖项
~0–265KB