首页 > 解决方案 > 如何在指定的时间内从 mpsc::channel 读取而没有不稳定的功能或外部 crate?

问题描述

我正在尝试在指定的时间内连续读取 a Receiver。我想出了以下解决方案

pub fn get<T>(
    rx: &Receiver<T>,
    get_duration: time::Duration,
) -> Result<(), Err> {
    let (dur_tx, dur_rx) = channel();
    let _ = thread::spawn(move || {
        // timer to kill receiving
        thread::sleep(get_duration);
        let _ = dur_tx.send("tick");
    });

    let mut time_to_break = false;
    while time_to_break == false {
        match rx.try_recv() {
            Ok(resp) => {
                //...
            }
            Err(_) => ()
        }
        thread::sleep(time::Duration::from_millis(1)); // avoid using cpu 100%
        let _ = dur_rx.try_recv().map(|_| time_to_break = true);
    }
    Ok(())
}

select在没有不稳定或不推荐使用的功能(例如)或外部板条箱的情况下,有没有更好的方法?

标签: rusttimeoutchannel

解决方案


你可以用 来做到这一点recv_timeout,它也应该更整洁:

pub fn get<T>(rx: &Receiver<T>, get_duration: Duration) -> Result<(), Error> {
    let start_time = Instant::now();
    loop {
        let now = Instant::now();
        if start_time + get_duration > now {
            let duration = start_time + get_duration - now;
            match rx.recv_timeout(duration) {
                Ok(resp) => {
                    // handle message
                }
                Err(RecvTimeoutError::Timeout) => break,
                Err(RecvTimeoutError::Disconnected) => {
                    // handle disconnect
                }
            }
        } else {
            break;
        }
    }
    Ok(())
}

稳定后recv_deadline,您可以使这更简单,因为您只需计算一次截止日期,然后继续通过它,而不是每次迭代都重新计算新的持续时间。


编辑:当它变得稳定时你应该使用的一个例子recv_deadline是我刚刚给你的代码中的一个错误。Duration总是正数,但我最初的计算没有检查以防止下溢,这会导致间歇性恐慌。我现在已经更新它以确保不会发生这种情况。

下面是使用截止日期(在 Nightly Rust 中)的样子:

#![feature(deadline_api)]

pub fn get<T>(rx: &Receiver<T>, get_duration: Duration) -> Result<(), Error> {
    let deadline = Instant::now() + get_duration;
    loop {
        match rx.recv_deadline(deadline) {
            Ok(resp) => {
                // handle message
            }
            Err(RecvTimeoutError::Timeout) => break,
            Err(RecvTimeoutError::Disconnected) => {
                // handle disconnect
            }
        }
    }
    Ok(())
}

推荐阅读