超时后中止Rust中的评估

超时后中止Rust中的评估,rust,timeout,Rust,Timeout,我在Rust中有一个函数(我没有写),它要么在毫秒内返回,要么在失败前研磨约10分钟 我想把对这个函数的调用包装成这样的东西:如果运行时间超过10秒,则返回一个选项,该选项为None,如果运行时间更短,则返回结果。但是,一旦调用了这个函数,我就无法找到任何方法来中断它的求值 例如: // This is the unpredictable function fn f() { // Wait randomly for between 0 and 10 seconds let mut

我在Rust中有一个函数(我没有写),它要么在毫秒内返回,要么在失败前研磨约10分钟

我想把对这个函数的调用包装成这样的东西:如果运行时间超过10秒,则返回一个
选项
,该选项为
None
,如果运行时间更短,则返回结果。但是,一旦调用了这个函数,我就无法找到任何方法来中断它的求值

例如:

// This is the unpredictable function
fn f() {
    // Wait randomly for between 0 and 10 seconds
    let mut rng = rand::thread_rng();
    std::thread::sleep(std::time::Duration::from_secs(rng.gen_range(0, 10)));
}

fn main() {
    for _ in 0..100 {
        // Run f() here but so that the whole loop takes no more than 100 seconds
        // by aborting f() if it takes longer than 1 second
    }
}
我已经找到了一些方法,可以使用带有超时的futures,但是我想尽量减少开销,而且我不确定为每个函数调用创建futures的代价有多高,因为它会被调用很多次


多亏了

异步执行的开销可能很小,特别是因为您的函数至少在毫秒内运行,这已经非常慢了

类似这样的方法会奏效:

use rand::Rng;
use std::time::Duration;
use tokio::time::timeout;

async fn f() -> i32 {
    // Wait randomly for between 0 and 10 seconds
    let mut rng = rand::thread_rng();
    tokio::time::delay_for(Duration::from_secs(rng.gen_range(0, 10))).await;
    // return something
    1000
}

#[tokio::main]
async fn main() {
    for _ in 0..100 {
        if let Ok(result) = timeout(Duration::from_secs(1), f()).await {
            println!("result = {}", result);
        } else {
            // took too long
        }
    }
}


与以往一样,在性能方面,如果您担心某个特定方法可能会很慢,请测试该理论,而不是假设您是正确的。性能特征往往令人惊讶。

这是否回答了您的问题@SCappella我看到了那个线程,但我不认为它完全符合我的情况,因为这涉及到生成整个线程,这对于我正在做的事情来说太昂贵了。我认为下面Peter的解决方案通过使用未来而不是线程来解决这个问题。或者,只解决停止问题(显然是在开玩笑)。这是一个写得很好的问题,@user42257。感谢您的回答,但它似乎仍然愿意在打印“result=1000”之间等待超过1秒。也就是说,我不认为超时实际上是中止计算,else语句永远不会运行。@user42257
thread::sleep
是一个阻塞操作,因此不应该在
异步
函数中使用。这就是为什么这不起作用的原因。您的函数可能也在阻塞,因此线程是唯一的选项。除非您的函数是为
async
使用而设计的,否则它只会阻塞整个线程。@SCappella啊,我不知道tokio::time::timeout有那个限制。我将研究如何用你之前推荐的链接开始的线程来实现这一点。我的错!我盲目复制OP的代码,没有测试。我现在已经更新了我的答案。