【问题标题】:Observable from list of timetamps可从时间戳列表中观察到
【发布时间】:2014-03-12 15:38:31
【问题描述】:

如果我有一个包含时间戳的对象列表 - 我如何制作一个在时间戳之间的相对时间触发事件的 observable?

例如。如果我有三个对象的时间戳分别为 2014-01-01 10:30、2014-01-01 10:45 和 2014-01-01 11:30,我希望第一个事件立即触发,然后在接下来的 15 分钟后触发,以及 45 分钟后的最后一个。

我怎样才能加快这个过程,使 1 分钟等于 1 秒?所以第一个事件会像以前一样立即触发,但下一个事件会晚 15 秒而不是 15 分钟,以此类推。

【问题讨论】:

    标签: c# .net system.reactive


    【解决方案1】:

    我确定有很多方法可以做到这一点,但这里有一个使用 Observable.Generate 在特定时间安排事件的快速示例。它使用事件列表 - 但鉴于它与迭代器一起使用,您可以轻松地调整它以使用另一个源:

    void Main()
    {
        var now = DateTime.Now;
    
        var events = new List<Tuple<DateTime, string>> {
            Tuple.Create(now.AddSeconds(5), "A"),
            Tuple.Create(now.AddSeconds(10), "B"),
            Tuple.Create(now.AddSeconds(15), "C")
        };
    
        var eventSource = Observable.Generate(
            (IEnumerator<Tuple<DateTime,string>>)events.GetEnumerator(),
            s => s.MoveNext(),
            s => s,
            s => s.Current.Item2, // the data
            s => s.Current.Item1); // the timing
    
        eventSource.Subscribe(Console.WriteLine);                       
    }
    

    这会在启动后写出“A”、“B”和“C”以及 5、10 和 15 秒。

    为了加快时间,您可以围绕如何解释计划时间设置一些逻辑。使用HistoricalScheduler 的另一种方式。有关这方面的一些见解,请参阅 this answer

    【讨论】:

    • HistoricalScheduler 听起来很有趣。以前从未听说过那个。 Observable.Generate() 看起来也不错。谢谢!
    • 如果日期不正确,这可能不起作用。它may 不会拉下一个并将其安排在前一个之前。虽然我不确定。 RX 源码中 Generate 的代码很复杂。
    • 是的,它希望事件是有序的。我不想生活在一个枚举器乱序提供它们的世界里!那将是精神上的。如果你需要检查它,你可以很容易地 - 但它闻起来就像你“做错了(tm)”对我来说。此外,针对 running 调度程序的乱序事件在此处的所有实现中都可能存在问题。 Generate 实际上确实很好因为它只在前一个事件完成时安排下一个事件,因此可以防止调度程序饥饿。
    【解决方案2】:

    最简单的方法是像这样合并可枚举的可观察对象

    IEnumerable<Tuple<DateTimeOffset,string>> timeStamps = ...;
    IObservable<Tuple<DateTimeOffset,string>> eventStamps = timeStamps
        .Select(s => Observable.Timer(s.Item1).Select(e=>s))
        .Merge();
    

    根据 James World 的回答,要加快或减慢时间,您可以将历史调度程序添加为 Timer 的第二个参数。 (给他点分数。在我阅读他的答案之前我不知道)

    Observable.Timer(s.Item1, historicalScheduler)
    

    如果您想知道为什么是 DateTimeOffset 而不是 DateTime,请查看 DateTime vs DateTimeOffset

    好消息是,如果 timeStamps 是 IEnumerableIObservable,上面的代码就可以工作。合并的重载适用于任何一个。

    【讨论】:

    • ...如果您真的真的关心DateTimeDateTimeOffset 的辩论,请查看nodatime
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 2020-04-20
    • 1970-01-01
    相关资源
    最近更新 更多