我正在构建一个大量使用RX的WP7应用程序,遇到了一个问题。当添加值大于20ms的Throttle时,会显著降低性能。
下面的片段指出了问题:
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将从线程池创建一个线程,不会阻塞UI,它应该非常高效,不是吗?
问题那么,为什么性能如此缓慢呢。我是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毫秒打印一个数字,但它没有打印任何数字。
这并不是说它很慢——您所描述的正是Throttle的行为。
当流在指定的持续时间内停止生成值时,Throttle会生成一个值。
让我把你的简历分解一下:
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毫秒内不会出现任何情况。