Window Operator不能自行运行?

时间:2011-01-25 11:28:15

标签: c# system.reactive

我有一些代码,我期望以某种方式工作,但事实并非如此,我想知道我做错了什么:

class Program
{
    static void Main(string[] args)
    {
      var ints = Observable.Interval(TimeSpan.FromMilliseconds(1000));
      var windowed = ints.Window(() => ints.Select(i => i / 3).DistinctUntilChanged());

      windowed.Subscribe(HandleNewWindow);

      Console.ReadLine();
    }

    public static void HandleNewWindow(IObservable<long> ints)
    {
      Console.WriteLine("New sequence received");
      ints.Subscribe(Console.WriteLine);
    }
  }

此输出应为:

收到新序列 0
1
2
收到新序列
3
4
5
收到新序列
6
7
8
...

但它是:

收到新序列 0
收到新序列
1
收到新序列
2
收到新序列
3
收到新序列
4
收到新序列
5
收到新序列
6
...

请注意,如果我使用不同的行来定义我的窗口,例如:

var windowed = ints.Window(() => Observable.Interval(TimeSpan.FromMilliseconds(3000)));

然后一切正常。

Window是否存在使用从Observable派生的窗口关闭的问题,或者我是否遗漏了重要的东西?

2 个答案:

答案 0 :(得分:1)

您需要使用Publish运算符来创建可以共享源的订阅的可观察对象。看起来每次关闭窗口时,它都会在内部设置对源的新订阅。使用发布可确保您不会每次都开始新的间隔

您还需要将窗口关闭选择器更改为仅在您希望关闭窗口时触发。

class Program
{
    static void Main(string[] args)
    {
        var ints = Observable.Interval(TimeSpan.FromMilliseconds(1000))
            .Publish(new Subject<long>());

        var closeOnValues = ints.Where(ShouldClose);

        var windowed = ints.Window(() => closeOnValues);

        windowed.Subscribe(HandleNewWindow);

        Console.ReadLine();
    }

    public static void HandleNewWindow(IObservable<long> ints)
    {
        Console.WriteLine("New sequence received");
        ints.Subscribe(Console.WriteLine);
    }

    public static bool ShouldClose(long index)
    {
        var notZero = index != 0;
        var countIsMultipleOfThree = (index + 1) % 3 == 0;

        return notZero && countIsMultipleOfThree;
    }
}

答案 1 :(得分:0)

我有一些看起来更像我的原始代码并产生预期值的东西。 我仍然不明白为什么这个代码有效而不是另一个代码,但我认为詹姆斯·海伊在他说某种重新订阅发生在幕后的时候会把它钉住。

class Program
{
    static void Main(string[] args)
    {
        var ints = Observable.Interval(TimeSpan.FromMilliseconds(1000));
        var windowClosings = ints
            .Select(i => i / 3)
            .DistinctUntilChanged()
            .SkipWhile((i) => i == 0)
            .Publish(new Subject<long>());
        var windowed = ints.Window(() => windowClosings);

        windowed.Subscribe(HandleNewWindow);

        Console.ReadLine();
    }

    public static void HandleNewWindow(IObservable<long> ints)
    {
        Console.WriteLine("New sequence received");
        ints.Subscribe(Console.WriteLine);
    }
}

除了仅删除第一个windowClosing的SkipWhile之外,这里的主要区别在于我必须发布windowClosings(而不是原始的Observable)。

仍然不能100%确定为什么我必须这样做。