Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Rx中先进的历史流和实时流_C#_.net_Datetime_System.reactive - Fatal编程技术网

C# Rx中先进的历史流和实时流

C# Rx中先进的历史流和实时流,c#,.net,datetime,system.reactive,C#,.net,Datetime,System.reactive,我有一个hot-observable,我通常在下面使用一个普通的主题来实现,这样感兴趣的人就可以订阅一个实时的通知流 现在,我想保留该实时流,但也要公开所有事件的历史流,这些事件已经和绝对时间附在这些通知上,以了解它们确切发生的时间,并允许订阅者在重播年表之前将历史流提前到任何时间点 我相信这大部分可以通过a和它的先进方法来实现,但我不确定具体如何实现 是否使用来节省所需的事件时间 是否需要将实时流缓存到历史记录中,然后使用HistoricalScheduler回放历史记录 如何为同一个源实

我有一个hot-observable,我通常在下面使用一个普通的
主题
来实现,这样感兴趣的人就可以订阅一个实时的通知流

现在,我想保留该实时流,但也要公开所有事件的历史流,这些事件已经和绝对时间附在这些通知上,以了解它们确切发生的时间,并允许订阅者在重播年表之前将历史流提前到任何时间点

  • 我相信这大部分可以通过a和它的先进方法来实现,但我不确定具体如何实现
  • 是否使用来节省所需的事件时间
  • 是否需要将实时流缓存到历史记录中,然后使用HistoricalScheduler回放历史记录
如何为同一个源实现这两个流,或者换句话说,如何将下面的内容适用于当前的需求


[参见标题]

历史调度程序
为您提供的是控制调度程序虚拟时间向前运动的能力

你没有得到的是随时间推移的随机访问。随着虚拟时间的提前,将执行计划的操作,因此必须提前计划这些操作。过去计划的任何操作(即在
HistoricalScheduler.Now
value之后的绝对时间)都会立即执行

要重播事件,您需要以某种方式记录它们,然后使用
HistoricalScheduler
的实例对它们进行调度,然后提前时间

当您提前时间时,计划的操作将在其到期时间执行-当可观察对象向其订户发送
OnXXX()
时,计划程序的
Now
属性将具有当前虚拟时间

每个订阅者都需要访问自己的调度程序,以便独立于其他订阅者控制时间。这实际上意味着为每个订户创建一个可观察的

下面是我制作的一个快速示例(如果您引用nuget package rx main,它将在LINQPad中运行)

首先,我录制一个实时流(以完全非生产方式!),将事件记录到列表中。正如您所建议的,使用
TimeStamp()
可以很好地捕获时间:

/* record a live stream */
var source = Observable.Interval(TimeSpan.FromSeconds(1));
var log = source.Take(5).Timestamp().ToList().Wait();


Console.WriteLine("Time now is " + DateTime.Now);
现在我们可以使用HistoricalScheduler结合巧妙地使用Generate来调度事件。请注意,这种方法可以防止大量已安排的事件提前排队-相反,我们只是一次安排一个:

var scheduler = new HistoricalScheduler();

/* set up the scheduling of the recording events */
var replay = Observable.Generate(
    log.GetEnumerator(),
    events => events.MoveNext(),
    events => events,
    events => events.Current.Value,
    events => events.Current.Timestamp,
    scheduler);
现在,当我们订阅时,您可以看到
HistoricalScheduler
Now
属性具有事件的虚拟时间:

replay.Subscribe(
    i => Console.WriteLine("Event: {0} happened at {1}", i,
    scheduler.Now)); 
最后,我们可以启动日程安排(使用start()只尝试播放所有事件,而不是使用
AdvanceTo
移动到特定时间-就像执行
AdvanceTo(DateTime.MaxValue);

我的产出是:

Time now is 07/01/2014 15:17:27
Event: 0 happened at 07/01/2014 15:17:23 +00:00
Event: 1 happened at 07/01/2014 15:17:24 +00:00
Event: 2 happened at 07/01/2014 15:17:25 +00:00
Event: 3 happened at 07/01/2014 15:17:26 +00:00
Event: 4 happened at 07/01/2014 15:17:27 +00:00
结果是,您可能最终不得不在这个工具上创建自己的API,以获得适合您特定用途的东西。它给您留下了相当多的工作,但仍然是非常强大的东西

很好的一点是,实时可观测和重放的可观测实际上看起来没有什么不同——只要您记住始终参数化您的调度程序(!)——因此可以轻松地在它们上面运行相同的查询,时间查询都与调度程序的虚拟时间一起工作

我用它来测试对旧数据的新查询,在商业场景中效果非常好

它不想成为一个传输控件,比如在GUI中提供在时间上来回滚动的服务。通常情况下,您会大块运行历史记录,存储新查询的输出,然后使用这些数据在GUI中进行后续显示,以便用户可以通过您提供的其他机制轻松地来回移动德

最后,您不需要
ReplaySubject
来缓存实时流;但是您确实需要一些记录事件以进行回放的方法—这可能只是一个写入日志的观察者

Time now is 07/01/2014 15:17:27
Event: 0 happened at 07/01/2014 15:17:23 +00:00
Event: 1 happened at 07/01/2014 15:17:24 +00:00
Event: 2 happened at 07/01/2014 15:17:25 +00:00
Event: 3 happened at 07/01/2014 15:17:26 +00:00
Event: 4 happened at 07/01/2014 15:17:27 +00:00