合并两个IObservable时出现意外行为

时间:2016-01-28 15:52:21

标签: c# .net system.reactive

我最近有以下情况"玩Rx" -project:

class Program
{
    static void Main(string[] args)
    {
        var observable1 = Observable.Create<int>(
               (Func<IObserver<int>, IDisposable>)GenerateSequence);
        var observable2 = Observable.Create<int>(
               (Func<IObserver<int>, IDisposable>)GenerateSequence);
        var merged = observable1.Merge(observable2);

        observable1.Subscribe(i => Console.WriteLine("1: " + i.ToString()));
        observable2.Subscribe(i => Console.WriteLine("2: " + i.ToString()));
        merged.Subscribe(i => Console.WriteLine("Merged: " + i.ToString()));

        Console.ReadLine();
    }

    private static int count = 0;

    private static IDisposable GenerateSequence(IObserver<int> observer)
    {
        ThreadPool.QueueUserWorkItem((o) =>
        {
            while (true)
            {
                observer.OnNext(count++);
                Thread.Sleep(500);
            }
        });
        return Disposable.Empty;
    }
}

现在,我希望看到像

这样的东西
1: 0
2: 1
Merged: 0
Merged: 1
1: 2
2: 3
Merged: 2
Merged: 3

相反,我正在看

1: 0
2: 1
Merged: 2
Merged: 3
1: 4
2: 5
Merged: 6
Merged: 7

如果我用

替换循环
while (true)
{
    observer.OnNext(r.Next(0, 1000));
    Thread.Sleep(500);
}

对于Random的静态或局部实例r,合并后的序列中有两个单独序列的其他数字!

我从count++的一次调用中看不到r.Next(0, 1000)observer.OnNext(...)如何多次执行。 Merge怎么样我不明白?

P.S。:我试图通过锁定或分离两个线程的循环时间来消除竞争条件,但结果没有改变,因此我将这些尝试排除在外。

编辑:似乎GenerateSequence被调用了4次,因此4个线程被调整为增加count。虽然这解释了我所看到的,但我不明白为什么会这样。

1 个答案:

答案 0 :(得分:4)

  • 当您订阅observable1时,您订阅了Observable.Create(GenerateSequence),该GenerateSequence会调用observable2并开始循环播放。
  • 当您订阅Observable.Create(GenerateSequence)时,您订阅了GenerateSequence,该merged会调用Observable.Merge(observable1, observable2)并开始循环播放。
  • 当您订阅observable1时,您订阅了observable2,订阅了GenerateSequencePublish()。我们在前两点看到了当你做这些事时会发生什么。

最终结果是对var observable1 = Observable .Create<int>((Func<IObserver<int>, IDisposable>)GenerateSequence) .Publish(); var observable2 = Observable .Create<int>((Func<IObserver<int>, IDisposable>)GenerateSequence) .Publish(); var merged = observable1.Merge(observable2); observable1.Subscribe(i => Console.WriteLine("1: " + i.ToString())); observable2.Subscribe(i => Console.WriteLine("2: " + i.ToString())); merged.Subscribe(i => Console.WriteLine("Merged: " + i.ToString())); observable1.Connect(); observable2.Connect(); 的四次调用。

要获得与您正在寻找的效果非常接近的效果,您需要查看observable1

observable2

IConnectableObservableIObservable现在属于Observable.Create类型,这意味着他们不会订阅他们的基础Connect(在您的情况下为1: 0 Merged: 0 2: 1 Merged: 1 1: 2 Merged: 2 2: 3 Merged: 3 ... ),直到他们已调用{{1}}。

输出

{{1}}