【问题标题】:How do I perform interruptible sleep in Rust?如何在 Rust 中执行可中断睡眠?
【发布时间】:2022-01-03 23:16:05
【问题描述】:

我正在编写一个 Rust 程序,它每 2 秒执行一次操作。该程序还使用ctrlc crate 来处理中断。但是,在某些情况下,我必须等待最多 2 秒才能终止进程。我正在使用默认的std::thread::sleep 函数,我似乎无法中断。

我的问题来了。我可以让我的程序以可中断的方式休眠吗?换句话说,Rust 是否具有中断睡眠程序的默认功能?我知道当收到 SIGINT 信号时,C 会自动中断任何睡眠功能。

【问题讨论】:

  • 你能分享一个 sn-p 来复制你的问题吗?信号处理程序在捕获 SIGINT 时是否退出进程?当a)在主线程上休眠或b)在生成的线程上休眠并在主线程上加入()时,我无法重现该问题。程序等待睡眠到期的唯一时间是ctrlc 处理程序没有调用std::process::exit

标签: multithreading rust sleep sigint


【解决方案1】:

如果您只想清理并退出,那么您可以按照其他答案的建议在信号处理程序中调用std::process::exit。但是,如果您希望您的线程停止以便您的应用程序可以继续执行其他任务,您可以使用通道和recv_timeout 来获得可中断的睡眠:

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

let (send, recv) = mpsc::channel();

thread::spawn(move || {
    // When you want to sleep
    if let Ok(_) = recv.recv_timeout (Duration::from_secs (2)) {
        // Sleep was interrupted
        return;
    }
    // Slept for 2s, proceeding
});

// And elsewhere when you want to interrupt the thread:
send.send(());

【讨论】:

    【解决方案2】:

    您的信号处理程序需要在捕获信号时让正在运行的线程以某种方式停止或退出进程。

    退出过程很简单:清理完成后在信号处理程序中调用std::process::exit()

    将信号转发到你的睡眠线程更难,你可以通过在捕获 SIGINT 时在Arc<AtomicBool> 中设置一些标志来做到这一点,并在两次检查之间用较短的间歇性睡眠而不是一次较长的睡眠重复检查该标志.

    您还可以提出一个基于通道的解决方案,您的 ctrlc 处理程序通过广播通道与正在运行的线程进行通信,并在退出进程之前等待它们以某种done 消息进行响应。这个done 消息可以通过关闭处理程序传递给正在运行的线程的通道的发送端。然后它可以在使用std::process::exit 强制退出之前等待超时。

    【讨论】:

    • 我使用 ctrlc crate 实现了我提出的解决方案,尽管我只在 linux 上进行了测试。处理程序不会在 Windows 上执行吗?
    • 我完全忘记了我可以在信号处理程序中进行清理。很抱歉浪费了您的时间。谢谢!
    • 执行了,我只是没执行std::process::exit
    猜你喜欢
    • 1970-01-01
    • 2020-05-02
    • 2017-12-27
    • 2014-07-07
    • 1970-01-01
    • 2013-01-10
    • 2020-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多