请教一下,有如下代码:
let task_pool: Arc<Mutex<Vec<Task>>> = Arc::new(Mutex::new(vec![]));
{
let task_pool = Arc::clone(&task_pool);
thread::spawn(move || {
loop {
let pool = &mut *task_pool.lock().unwrap();
// 遍历pool找到第一个需要运行的任务,复制任务,unlock锁
// 运行它,每个任务通常需要进行较长时间(一般大于10分钟)
// 任务的形式用`powershell`调用`exe`文件
thread::sleep(time::Duration::from_secs(1));
}
});
}
another_func(Arc::clone(&task_pool));
整个代码是包裹在#[tokio::main]
里的(其实是一个使用warp的后端,在个人电脑上用的,自己给自己提供服务,以html为界面的web程序),所以用了稍微有点扭曲的办法。我希望线程可以按顺利运行task_pool
里的任务(假如task.status == 0
就表示任务需要运行),而且希望主线程可以随时更改task_pool
里的数据,包括可以随时取消正在运行中的task
。
我目前的想法是每次运行新任务就spawn
一个新线程,每秒钟遍历一次pool
,发现运行中的线程被取消了就直接杀死线程。然后再遍历pool
获取下一个需要运行的task
。如果是其他任务被改变则无视。但是找来找去发现不了怎么杀死线程。我现在的唯一想法是直接park
挂起这个线程?然后开一个新线程,这样好吗?(程序一般运行不超过24小时。)
请教下还有更好的办法吗?
更新:8月11日
最后用subprocess
实现了。
更新:8月12日
subprocess
库的kill
好像不太成功的样子。
更新:8月13日
听取大家的意见用tokio::process::command和tokio_select解决了。tokio的child里的kill的案例就是这个,触发式杀死child。这种写法比手动写逻辑舒服得多。
至于kill不成功,是第一次用犯傻了,用command::new("cmd")::args(&["/C", "ffmpeg ..."])
调用程序的话,kill之后,实际上ffmepg不会停止。直接用command::new("ffmpeg")::args(&[&cmd])
没有任何问题。
评论区
写评论主要是我线程里面使用
process
调用了已经编译好的ffmpeg.exe
。如果直接结束好像会出问题的样子。--
👇
WarriorOfDarkness: 都跑再tokio里了还thread干嘛直接async.await 想结束任务跳出作用域就行
tokio spawn里面就行了。
都跑再tokio里了还thread干嘛直接async.await 想结束任务跳出作用域就行