【发布时间】:2016-12-16 17:34:06
【问题描述】:
我刚开始使用响应式编程,我知道的只是编写代码,但还不足以弄清楚当我没有得到我期望的结果时会发生什么。除了博客文章,我真的没有可用的导师。我还没有找到一个很好的解决方案来解决我遇到的情况,我很好奇正确的方法。
问题:
我需要获取一个 Foo,它部分由 Bar 对象数组组成。我从 Web 服务中获取 Bar 对象。因此,我将每个 Web 服务调用表示为一个 IObservable,我希望在完成之前从其中包含 0 或 1 个元素。我想做一个 IObservable,它将:
- 订阅每个 IObservable 实例。
- 等待最多 2 秒超时。
- 当两个序列都完成或超时发生时:
- 使用生成的任何 Bar 对象创建一个数组(可能有 0 个。)
- 使用该 Bar[] 生成 Foo 对象。
我用这段代码完成了这个:
public Foo CreateFoo() {
var producer1 = webService.BarGenerator()
.Timeout(TimeSpan.FromSeconds(2), Observable.Empty<Bar>());
var producer2 = // similar to above
var pipe = producer1.Concat(producer2);
Bar[] result = pipe.ToEnumerable().ToArray();
...
}
这似乎不对,原因有很多。最明显的是 Concat() 将串行而不是并行启动序列,所以这是一个 4 秒的超时。我真的不在乎它是否阻塞,它实际上对我正在使用的架构很方便。我很满意这种方法成为 IObservable 的生成器,但是这里有一些额外的注意事项,当我尝试时,这似乎会带来挑战:
- 如果生产者 1 和生产者 2 的结果都产生结果,我需要最后一个数组来按顺序排列它们。
- 我想使用 TestScheduler 来验证超时但还没有成功,我显然根本不懂调度程序。
- 归根结底,这是一个拉动模型,无论 Foo 在一个不同的点需要它,并且“即时”接收它没有任何价值。也许这会倾斜“不要使用 Rx”的答案。老实说,我被卡住了,我切换到了基于任务的 API。但我想看看如何使用 Rx 来解决这个问题,因为我想学习。
【问题讨论】:
-
我觉得 Zip 比 Concat 更适合您的问题。
-
@EricLippert:嗯......我必须做一些工作以确保我之后按正确的顺序排列它们,但我确实知道这会更好。
-
为什么很难把它们整理好?
firstBars.Zip(secondBars, (first, second) => new { first, second }现在你有一个可观察的{first, second}对。 -
现在这个解决方案可能不正确,因为如果第一个超时,您仍然想要第二个的酒吧?
-
@EricLippert:是的,我猜 Zip 在这种情况下会阻塞。如果我有某种“空结果”空对象怎么办?到目前为止,我的想法都围绕着某种基于 WaitHandle 的解决方案。
标签: c# system.reactive