【问题标题】:How would I write this code with Reactive Programming?我将如何使用响应式编程编写此代码?
【发布时间】: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. 如果生产者 1 和生产者 2 的结果都产生结果,我需要最后一个数组来按顺序排列它们。
  2. 我想使用 TestScheduler 来验证超时但还没有成功,我显然根本不懂调度程序。
  3. 归根结底,这是一个拉动模型,无论 Foo 在一个不同的点需要它,并且“即时”接收它没有任何价值。也许这会倾斜“不要使用 Rx”的答案。老实说,我被卡住了,我切换到了基于任务的 API。但我想看看如何使用 Rx 来解决这个问题,因为我想学习。

【问题讨论】:

  • 我觉得 Zip 比 Concat 更适合您的问题。
  • @EricLippert:嗯......我必须做一些工作以确保我之后按正确的顺序排列它们,但我确实知道这会更好。
  • 为什么很难把它们整理好? firstBars.Zip(secondBars, (first, second) =&gt; new { first, second } 现在你有一个可观察的 {first, second} 对。
  • 现在这个解决方案可能不正确,因为如果第一个超时,您仍然想要第二个的酒吧?
  • @EricLippert:是的,我猜 Zip 在这种情况下会阻塞。如果我有某种“空结果”空对象怎么办?到目前为止,我的想法都围绕着某种基于 WaitHandle 的解决方案。

标签: c# system.reactive


【解决方案1】:
    var pipe = producer1
        .Merge(producer2)
        .Buffer(Observable.Timer(TimeSpan.FromSeconds(2), testScheduler))
        .Take(1);

    var subscription = pipe
        .Select(list => new Foo(list.ToArray())
        .Subscribe(foo => {} /* Do whatever you want with your foo here.*/);

Buffer 获取窗口期间发出的所有元素(在我们的例子中为两秒),并输出一个列表。

如果您想坚持使用拉取模型,而不是订阅,您可以这样做:

var list = await pipe;
var foo = new Foo(list.ToArray());

//....

【讨论】:

  • 这看起来应该可以工作,并且与测试调度程序一起运行。为了完成排序,我创建了一个类,让我可以将整数“排序顺序”附加到任何给定值。然后,在最后阶段,我对该可枚举对象进行排序并将其转换回字符串序列。
猜你喜欢
  • 1970-01-01
  • 2021-09-04
  • 1970-01-01
  • 1970-01-01
  • 2014-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多