Как я могу читать из mpsc :: channel в течение определенного времени без нестабильных функций или внешних ящиков? - PullRequest
1 голос
/ 14 марта 2019

Я пытаюсь непрерывно читать из 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) или внешних ящиков?

1 Ответ

2 голосов
/ 14 марта 2019

Вы можете сделать это с помощью 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(())
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...