.net 如何使用Rx以非阻塞方式观察值?

.net 如何使用Rx以非阻塞方式观察值?,.net,system.reactive,.net,System.reactive,我试着观察一个计时器,它的处理器比间隔长。 为了做到这一点,我想安排对某种线程池、任务池或其他东西的观察 我尝试了threadpool、taskpool和newthread,但都没有成功。 有人知道怎么做吗? 例如: 你所要求的是一个坏主意,因为你最终会耗尽可用资源(因为创建线程的速率>线程完成速率)。相反,为什么不在前一个项目完成后安排一个新项目呢 在您的特定示例中,您需要将isScheduler传递给Observable.Timer,而不是尝试使用ObserveOn。Paul说这是一个坏主意

我试着观察一个计时器,它的处理器比间隔长。 为了做到这一点,我想安排对某种线程池、任务池或其他东西的观察

我尝试了threadpool、taskpool和newthread,但都没有成功。 有人知道怎么做吗? 例如:


你所要求的是一个坏主意,因为你最终会耗尽可用资源(因为创建线程的速率>线程完成速率)。相反,为什么不在前一个项目完成后安排一个新项目呢


在您的特定示例中,您需要将isScheduler传递给Observable.Timer,而不是尝试使用ObserveOn。

Paul说这是一个坏主意是正确的。您在逻辑上创建了一种情况,排队的操作可能会耗尽系统资源。您甚至可以发现它在您的计算机上工作,但在客户的计算机上失败。可用内存、32-/64位处理器等都可能影响代码

然而,修改代码以使其满足您的需要是很容易的

不过首先,只要观察者在下一个预定事件之前完成,
Timer
方法将正确地安排计时器事件。如果观察者尚未完成,则计时器将等待。请记住,可观察计时器是“冷”可观察的,因此对于每个订阅的观察者,实际上都有一个新的可观察计时器。这是一对一的关系

此行为可防止计时器无意中耗尽您的资源

因此,正如您当前定义的代码一样,
OnNext
每1000毫秒调用一次,而不是每100毫秒调用一次

现在,要允许代码以100毫秒的计划运行,请执行以下操作:

Observable
    .Timer(TimeSpan.Zero, TimeSpan.FromMilliseconds(100))
    .Select(x => Scheduler.NewThread.Schedule(() =>
    {
        count++;
        Thread.Sleep(TimeSpan.FromMilliseconds(1000));
    }))
    .Subscribe(x => { });
实际上,此代码是一个可观察的
IObservable
,其中每个一次性操作都是需要1000毫秒才能完成的预定操作

在我的测试中,这运行得很好,并且正确地增加了计数

我确实尝试耗尽我的资源,发现将计时器设置为每毫秒运行一次,我很快得到一个
系统。OutOfMemoryException
,但如果我将设置更改为每两毫秒运行一次,我发现代码会运行。然而,当代码运行并创建大约500个新线程时,这确实消耗了超过500 MB的RAM。一点也不好


小心行事

如果你真的在不断地创造价值,其速度超过了你消费价值的速度,那么正如所指出的,你正在走向麻烦。如果你不能降低生产速度,那么你需要看看如何更快地消耗它们。也许您希望多线程观察器以使用多个内核

如果对观察者执行多线程处理,则可能需要小心处理无序的事件。您将在同一时间处理多个通知,并且所有的赌注都是先完成哪个处理(或者先到达某个竞争条件临界状态)

如果您没有处理流中的每个事件,请查看浮动的两个不同的
observelaston
实现。有线程在讨论它和它

ObserveLatestOn
将删除除最新通知以外的所有通知,该通知是在观察者处理以前的通知时发生的。当观察者处理完之前的通知后,它将收到最新的通知,并错过其间发生的所有通知


这样做的好处是,它可以防止比消费者更快的生产商产生压力。如果消费者因为负载而变慢,那么处理更多的通知只会变得更糟。删除不必要的通知可能会使负载减少到消费者可以跟上的程度。

创建速率与完成速率相同。只是实际操作需要时间。我希望将所有观察结果放在某种线程池/任务池上,以避免创建开销。我可以让SUBScription以一种异步的方式完成它的工作,我只是希望在rx中内置这种操作。Taskpool并不神奇,在这种情况下,您只需要填充Taskpool队列,直到它抛出一个错误。我会将调度放在Subscribe处理程序中,而不是使用Select。“你为什么不那样做?”尼亚尔·康诺顿——我是在将近两年前回答这个问题的。我不记得了。现在我看起来确实有点奇怪。我也在这里写了一篇关于有效实现ObserveLatestOn的博客文章:
Observable
    .Timer(TimeSpan.Zero, TimeSpan.FromMilliseconds(100))
    .Select(x => Scheduler.NewThread.Schedule(() =>
    {
        count++;
        Thread.Sleep(TimeSpan.FromMilliseconds(1000));
    }))
    .Subscribe(x => { });