Задержка в будущем возвращает ошибку (завершение работы) при опросе - PullRequest
0 голосов
/ 24 мая 2019

Я переписываю будущее Forward с Stream на Sink, добавляя тайм-аут при получении новых предметов. Я использую будущее Delay внутри структуры Forward, чтобы отслеживать время ожидания, но результатом всегда является Error(Shutdown).

Из документации timer::Error я вижу, что это должно возвращаться, только если будущее отброшено, но это не должно иметь место, так как оно все еще содержится в основной структуре.

Это минимальный тестовый пример, из которого я получаю тот же результат.

extern crate tokio; // 0.1.20

use std::thread::sleep;
use std::time::{Duration, Instant};
use tokio::prelude::*;
use tokio::timer::Delay;

fn main() {
    let mut delay = Delay::new(Instant::now() + Duration::from_millis(3000));

    sleep(Duration::from_millis(1000));

    match delay.poll() {
        Ok(Async::NotReady) => println!("Not ready"),
        Ok(Async::Ready(v)) => println!("Ready: {:?}", v),
        Err(e) => println!("{:?}", e),
    }
}

Вы можете увидеть работающий пример здесь

Я ожидаю либо получить Async:Ready(v), где v равно ().

1 Ответ

0 голосов
/ 01 июня 2019

A Delay работает вместе с Timer, и ошибка здесь указывает на то, что он не смог зарегистрироваться ни на одном.Хотя в документах иногда предполагается, что вы работаете в контексте Tokio, они упоминают это требование :

Эти типы должны использоваться в контексте Runtime или контекст таймера должен быть установлен явно.См. tokio-timer ящик для более подробной информации о том, как настроить контекст таймера.

Если вы хотите избежать ошибки, этого будет достаточно, чтобы запустить ее внутри задачи:

fn main() {
    tokio::run(futures::future::lazy(|| {
        let mut delay = Delay::new(Instant::now() + Duration::from_millis(3000));

        sleep(Duration::from_millis(1000));

        // "Not ready"
        match delay.poll() {
            Ok(Async::NotReady) => println!("Not ready"),
            Ok(Async::Ready(v)) => println!("Ready: {:?}", v),
            Err(e) => println!("{:?}", e),
        }

        Ok(())
    }))
}

Однако это не перейдет в состояние готовности, даже если вы будете ждать более 3000 миллисекунд.Если вы хотите использовать таймер времени выполнения, вам нужно будет запустить его как задачу:

fn main() {
    // "Ready: ()"
    tokio::run(
        Delay::new(Instant::now() + Duration::from_millis(3000))
            .map(|v| println!("Ready: {:?}", v))
            .map_err(|e| println!("{:?}", e)),
    )
}
...