【发布时间】:2015-06-09 10:13:50
【问题描述】:
假设我有一些 IEnumerator<T> 在 MoveNext() 方法中进行大量处理。
从该枚举器消耗的代码不仅消耗与可用数据一样快,而且偶尔会等待(其细节与我的问题无关)以同步需要恢复消耗的时间。但是当它下次调用MoveNext() 时,它需要尽可能快的数据。
一种方法是将整个流预先消耗到某个列表或数组结构中以进行即时枚举。然而,这会浪费内存,因为在任何一个时间点,只有一个项目正在使用,并且在整个数据无法放入内存的情况下,这将是令人望而却步的。
所以.net 中是否有一些通用的东西以某种方式包装一个枚举器/可枚举器,它预先异步预迭代底层枚举器几个项目并缓冲结果,以便它始终它的缓冲区中有许多可用的项目,并且调用 MoveNext 将永远不必等待?显然,消耗的项目,即由调用者的后续 MoveNext 迭代,将从缓冲区中删除。
注意我正在尝试做的部分事情也称为 Backpressure,并且,在 Rx 世界中,已经在 RxJava 中实现并且正在在Rx.NET 中讨论。 Rx(推送数据的 observables)可以被认为是枚举器的相反方法(枚举器允许拉取数据)。背压在拉取方法中相对容易,正如我的回答所示:只需暂停消费。推送时更难,需要额外的反馈机制。
【问题讨论】:
-
这看起来像您之前的问题的副本,您说您会编辑:stackoverflow.com/questions/30700154/a-pre-buffering-enumerator
-
@Asad 我删除了旧问题并创建了这个问题,因为现有问题的 cmets 与当前形式的问题根本不匹配。我希望这个能让我更清楚我真正想要什么。
-
这个问题似乎没有明显改变。您仍然存在这样的问题:一旦消费者耗尽缓冲区,在调用 MoveNext 时,预缓冲几个项目只会导致延迟两倍的频率。
-
消费者通常不会用尽缓冲区,这实际上 是在问题的第一个版本中缺少的重要限定。也就是说:
The code consuming from that enumerator does not just consume as fast as data is available, but occasionally waits [..] But when it does the next call to MoveNext(), it needs the data as fast as possible. -
@Asad 回复您的最后一条评论:您(和我的解决方案)有一个固定的缓冲区大小,这实际上足以解决我当前的问题,但不必修复它。预缓冲代码可以例如通过增加缓冲区的大小来适应消费者在长时间快速消费时威胁要完全耗尽缓冲区的消费者。使用 BlockingCollection(具有固定界限)很难做到的事情,但对于更动态的用例可能很有用,并且消除了消费者承诺固定大小的需要。
标签: c# .net enumerator backpressure