Window Operator не работает сам с собой? - PullRequest
1 голос
/ 25 января 2011

У меня есть немного кода, который, как я ожидал, будет работать таким образом, и это не так, мне интересно, что я делаю неправильно:

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 ]

1 голос
/ 25 января 2011

Вам нужно использовать оператор 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;
    }
}
0 голосов
/ 25 января 2011

У меня есть то, что больше похоже на мой оригинальный код и выдает ожидаемые значения.Я до сих пор не понимаю, почему этот код работает, а не другой, но я думаю, что Джеймс Хей прибил его, когда сказал, что какая-то повторная подписка происходит за кулисами.

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);
    }
}

Основные различия здесь,кроме SkipWhile, который удаляет только первое оконное закрытие, я должен был опубликовать закрывающие окна (а не исходные значения Observable).

Все еще не уверен на 100%, почему мне пришлось это сделать.

...