是否有更简单的方法让IObservable异步依赖于另一个IObservable?

时间:2011-02-07 22:07:51

标签: asynchronous system.reactive

我是RX的新手,我的理想场景运作良好,但在我看来,必须有一种更简单或更优雅的方式来实现这一目标。我所拥有的是IObservable<T>并且我希望以这样的方式订阅它,以便通过触发异步操作来最终得到IObservable<U>,,该异步操作为它看到的每个T生成U.

我到目前为止(效果很好,但看起来很麻烦)使用了一个中间事件流,就像这样:

public class Converter {
  public event EventHandler<UArgs> UDone;
  public IConnectableObservable<U> ToUs(IObservable<T> ts) {
    var us = Observable.FromEvent<UArgs>(this, "UDone").Select(e => e.EventArgs.U).Replay();
    ts.Subscribe(t => Observable.Start(() => OnUDone(new U(t))));
    return us;
  }
  private void OnUDone(U u) {
    var uDone = UDone;
    if (uDone != null) {
      uDone(this, u);
    }
  }
}

...

var c = new Converter();
IConnectableObservable<T> ts = ...;
var us = c.ToUs(ts);
us.Connect();

...

我确信我错过了一种更简单的方法来做到这一点......

2 个答案:

答案 0 :(得分:1)

SelectMany应该做你需要的事情,以平展IO<IO<T>>

Observable.Range(1, 10)
        .Select(ii => Observable.Start(() => 
             string.Format("{0} {1}", ii, Thread.CurrentThread.ManagedThreadId)))
        .SelectMany(id=>id)
        .Subscribe(Console.WriteLine);

答案 1 :(得分:0)

这正是SelectMany的用途:

IObservable<int> ts

IObservable<string> us = ts.SelectMany(t => StartAsync(t));

us.Subscribe(u => 
    Console.WriteLine("StartAsync completed with {0}", u));

...

private IObservable<string> StartAsync(int t)
{
    return Observable.Return(t.ToString())
        .Delay(TimeSpan.FromSeconds(1));
}

请注意,如果StartAsync具有变量完成时间,您可能会以与输入值不同的顺序接收输出值。