Дроссельная операция, приводящая к медленной работе на телефоне окна 7 - PullRequest
1 голос
/ 20 января 2012

Я создаю приложение WP7, которое интенсивно использует RX, и я столкнулся с проблемой. При добавлении Throttle со значением, превышающим 20 мс, это значительно снижает производительность.

Фрагмент ниже указывает на проблему:

var moveObs = Observable.FromEventPattern<MouseEventHandler, MouseEventArgs>(
                    h => this.MouseMove += h,
                    h => this.MouseMove -= h);

// Observe dragging
var yObs = (from x in moveObs
            select -(x.EventArgs.GetPosition(this).Y - _initY));

var result = yObs.SkipWhile(y => !_isDragging)
                 .Throttle(TimeSpan.FromMilliseconds(33));

result.TimeInterval()
      .Subscribe(x => Debug.WriteLine("Mouse move interval: " + x));

Вот вывод фрагмента:

'UI Task' (Managed): Loaded 'Microsoft.Devices.Sensors.dll'
The thread '<No Name>' (0x1e18) has exited with code 0 (0x0).
Mouse move interval: 80@00:00:04.1920000
Mouse move interval: -160@00:00:00.2900000
Mouse move interval: -126@00:00:00.6710000
The thread '<No Name>' (0x22a4) has exited with code 0 (0x0).
Mouse move interval: -90@00:00:01.0460000
The thread '<No Name>' (0x2514) has exited with code 0 (0x0).
Mouse move interval: -113@00:00:00.3250000
The thread '<No Name>' (0x270c) has exited with code 0 (0x0).
Mouse move interval: 108@00:00:12.1420000
The thread '<No Name>' (0x186c) has exited with code 0 (0x0).
Mouse move interval: 221@00:00:01.4860000

Так что, насколько я понимаю, Throttle создаст поток из пула потоков и не будет блокировать пользовательский интерфейс, и он должен быть достаточно эффективным, не так ли?

Вопрос Так почему же производительность такая низкая? Я новичок в RX, поэтому я, наверное, что-то здесь упускаю.

Редактировать

Вот еще один пример, который воспроизводит ту же проблему:

var oneNumberPerSecond = Observable.Interval(TimeSpan.FromMilliseconds(10));

var lowNums = from n in oneNumberPerSecond
              select n;


lowNums.Throttle(TimeSpan.FromMilliseconds(100))
       .TimeInterval()
       .Subscribe(lowNum => Debug.WriteLine(lowNum));

В моем понимании это должно печатать число каждые 100 мс, однако оно не печатает ни одного.

1 Ответ

2 голосов
/ 20 января 2012

Дело не в том, что он медленный - вы описали именно поведение Дросселя.

Дроссель создает значение, когда поток прекращает производство значения в течение указанной продолжительности.

Позвольте мне разобрать ваше воспроизведение:

var oneNumberPerSecond = Observable.Interval(TimeSpan.FromMilliseconds(10));

Это наблюдаемая холодная погода, которая выдает значение каждые 10 мсек.

var lowNums = from n in oneNumberPerSecond
              select n;

Это ничего не делает на самом деле. Это эквивалентно oneNumberPerSecond.Select(i => i)

lowNums.Throttle(TimeSpan.FromMilliseconds(100))

Это создает поток, который будет генерировать значение всякий раз, когда lowNums прекращает производить значение для 100 мсек. Но поскольку lowNums выдает значение каждые 10 мсек, не будет времени, когда ничего не произойдет для 100 мсек.

...