在同一个IObservable订阅中访问IObservable

时间:2011-10-10 20:41:08

标签: c# iterator system.reactive

以下是我尝试使用Reactive Extensions做的一个简单示例,但它不起作用

添加在此简单示例中不起作用

    public static void Main(string[] args)
    {
        var list = new List<int> { 1, 2, 3 };
        var obs = list.ToObservable();
        IDisposable subscription = obs.SubscribeOn(Scheduler.NewThread).Subscribe(p =>
        {
            Console.WriteLine(p.ToString());
            Console.WriteLine(Add(obs).ToString());
        },
        err => Console.WriteLine("Error"),
        () => Console.WriteLine("Sequence Completed")
        );
        Console.ReadLine();
        subscription.Dispose();
    }

    private static int Add(IObservable<int> wholeList)
    {
        int sum = 0;
        wholeList.ForEach(i => sum = sum + i);
        return sum;
    }

实际输出

1
_

期望输出

1
6
2
6
3
6
Sequence Completed
_

即。我想在每次迭代中执行一个方法Add(obs),其中obs本身就是正在进行迭代的冷IObservable吗?

2 个答案:

答案 0 :(得分:2)

改变这个:

IDisposable subscription = obs.SubscribeOn(Scheduler.NewThread)

到此:

IDisposable subscription = obs.ObserveOn(Scheduler.NewThread)

你应该注意到,就Rx而言,你做的事情很糟糕。你正在进出观察者。你应该尽可能避免这种情况。

因此,例如,避免这样:

    var list = new List<int> { 1, 2, 3 };
    var obs = list.ToObservable();

这是相同的:

    var obs = Observable.Range(1, 3);

整个static int Add(IObservable<int> wholeList)方法也很糟糕。它调用ForEach(通常应该警告你做错了)将值从可观察量中取出。这是可以发生死锁的地方。

已经存在一个名为Sum的可观察扩展名,它会返回IObservble<int>,但这并不会让您离开可观察对象。

所以尝试编写这样的代码:

var obs = Observable.Range(1, 3);

var query =
    from n in obs
    from s in obs.Sum()
    select new
    {
        Number = n.ToString(),
        Sum = s.ToString(),
    };

using (var subscription = query.SubscribeOn(Scheduler.NewThread).Subscribe(
    x =>
        {
            Console.WriteLine(x.Number);
            Console.WriteLine(x.Sum);
        },
    err =>
        Console.WriteLine("Error"),
    () =>
        Console.WriteLine("Sequence Completed")))
{
    Console.ReadLine();
}

我希望这会有所帮助。

答案 1 :(得分:1)

作为你的评论,我建议你让observable根据需要生成项目,而不是在订阅后做这些事情。在您的示例中,您可以执行以下操作:

var list = new List<int> { 1, 2, 3 };
var obs = list.ToObservable().Select(i => new Tuple<int,IObservable<int>>(i,list.ToObservable()));

obs.SubscribeOn(Scheduler.NewThread).Subscribe(t => {
  Console.WriteLine(t.Item1);
  SaveItems(t.Item2);
});