< 返回版块

eweca-d 发表于 2021-08-11 18:04

请教一下,有如下代码:

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])没有任何问题。

评论区

写评论
作者 eweca-d 2021-08-12 18:11

主要是我线程里面使用process调用了已经编译好的ffmpeg.exe。如果直接结束好像会出问题的样子。

--
👇
WarriorOfDarkness: 都跑再tokio里了还thread干嘛直接async.await 想结束任务跳出作用域就行

enginefuture 2021-08-12 17:40

tokio spawn里面就行了。

WarriorOfDarkness 2021-08-12 10:08

都跑再tokio里了还thread干嘛直接async.await 想结束任务跳出作用域就行

1 共 3 条评论, 1 页