Rx中的多个SelectMany

时间:2011-09-26 13:34:09

标签: observablecollection system.reactive observer-pattern

我有这样的界面:

interface IProcessor{
    IObservable<Item> Process(Item item);
}

我有一系列工人:

IProcessor[] _workers = ....

我想通过所有工人传递一个项目:

var ret = Observable.Return(item);
for (var i = 0; i < _workers.Length; i++)
{
    int index = i;
    ret = ret
        .SelectMany(r => _workers[index].Process(r))
    ;
}
return ret;

我对这看起来不太满意 - 有更清洁的方式吗?

2 个答案:

答案 0 :(得分:2)

这对我有用:

IObservable<Item> ret = _workers.Aggregate(
    Observable.Return(item),
    (rs, w) =>
        from r in rs
        from p in w.Process(r)
        select p);

请记住,这种可观察的聚合 - 无论是在您的问题还是在我的答案中 - 都可能导致内存问题(即堆栈溢出)。在我的测试中,我可以让400名工人工作,但500人造成了崩溃。

最好将IProcessor更改为不使用observable并实现这样的observable:

interface IProcessor{
    Item Process(Item item);
}

var f =
    _workers.Aggregate<IProcessor, Func<Item, Item>>(
            i => i,
            (fs, p) => i => p.Process(fs(i)));

var ret = Observable.Start(() => f(item), Scheduler.ThreadPool);

通过这种方法,我可以在堆栈溢出之前获得超过20,000个嵌套工作程序,并且结果几乎可以立即达到该级别。

答案 1 :(得分:0)

也许是这样的:?

var item = new Item();
_workers
  .ToObservable()
  .SelectMany(worker => worker.Process(item))
  .Subscribe(item => ...);

我假设工人可以并行处理该项目。

P.S。如果您想要顺序处理,那就是

var item = new Item();
_workers
  .ToObservable()
  .Select(worker => worker.Process(item))
  .Concat()
  .Subscribe(item => ...);