为什么poll()内部的Delay future在我的自定义Stream类型中不起作用?

时间:2019-04-10 09:31:05

标签: rust rust-tokio

我想每秒打印一次“ Hello”。

引用文档:

  

未来使用基于民意测验的模型。未来的使用者反复调用轮询功能。未来将尝试完成。如果将来能够完成,则返回Async :: Ready(value)。如果将来由于内部资源(例如TCP套接字)上的阻塞而无法完成,则会返回Async :: NotReady。

如果poll的返回值为NotReady,则我的Delay函数返回NotReady,但是没有输出任何内容到标准输出。

use futures::{Async, Future, Stream}; // 0.1.25
use std::time::{Duration, Instant};
use tokio::timer::Delay; // 0.1.15

struct SomeStream;

impl Stream for SomeStream {
    type Item = String;
    type Error = ();

    fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> {
        let when = Instant::now() + Duration::from_millis(1000);
        let mut task = Delay::new(when).map_err(|e| eprintln!("{:?}", e));
        match task.poll() {
            Ok(Async::Ready(value)) => {}
            Ok(Async::NotReady) => return Ok(Async::NotReady),
            Err(err) => return Err(()),
        }
        Ok(Async::Ready(Some("Hello".to_string())))
    }
}

fn main() {
    let s = SomeStream;
    let future = s
        .for_each(|item| {
            println!("{:?}", item);
            Ok(())
        })
        .map_err(|e| {});
    tokio::run(future);
}

1 个答案:

答案 0 :(得分:2)

这里的主要问题是缺少状态管理。每次轮询流时,您都在创建一个新的import java.io.*; import java.util.*; public class HelloWorld{ public static void main(String []args){ BigInteger i1 = new BigInteger("4343345345345"); BigInteger i2 = new BigInteger("4343453345345345"); BigInteger i3 = new BigInteger("22"); List<BigInteger> list = new ArrayList<>(); list.add(i1); list.add(i2); list.add(i3); System.out.println(Collections.min(list, Comparator.naturalOrder())); } } 未来,而不是一直坚持到解决为止。 这将导致永远不会看到任何项目流,因为这些期货仅被轮询一次,每次可能产生Delay

您需要使用NotReady类型跟踪将来的延迟。在这种情况下,可以使用一个选项,以便确定我们是否需要创建新的延迟。

SomeStream

#[derive(Debug, Default)] struct SomeStream { delay: Option<Delay>, } 的后续代码具有更好的错误处理和更惯用的结构,将变成这样:

SomeStream::poll

或者,甚至更好的方法是使用impl Stream for SomeStream { type Item = String; type Error = Box<dyn std::error::Error + Send + Sync>; // generic error fn poll(&mut self) -> Result<Async<Option<Self::Item>>, Self::Error> { let delay = self.delay.get_or_insert_with(|| { let when = Instant::now() + Duration::from_millis(1000); Delay::new(when) }); match delay.poll() { Ok(Async::Ready(value)) => { self.delay = None; Ok(Async::Ready(Some("Hello".to_string()))) }, Ok(Async::NotReady) => Ok(Async::NotReady), Err(err) => Err(err.into()), } } } 宏,它以更少的样板实现错误和try_ready!信号的返回。

NotReady

Playground