WP7 - 使用RX,订阅只触发一次,但OnNext()总是触发?

时间:2012-05-15 15:58:39

标签: c# windows-phone-7 system.reactive

好的我还有另一个有反应性延伸的游戏,特别是wp7。

我正在考虑GeoCoordinateWatcher positon改变事件,如此

var subject = new BehaviorSubject<GeoCoordinate>(GeoCoordinate.Unknown);
var watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default) { MovementThreshold = 0 };

watcher.PositionChanged += (o, args) =>
{
   var newLocation = args.Position.Location;

   if ((DateTime.Now - args.Position.Timestamp.DateTime) < locationTimeout)
   {
        subject.OnNext(newLocation);
    }
};

我这样订阅

MyLocation.StartGettingLocations()
 .Subscribe(pos =>
 {
       // Do something with the position
       PlotLine.Locations.Add(pos);
       bingMap.SetView(pos, 15);
 });

应用程序运行但问题是如果我在主题中放置了一个断点,订阅只发生一次.OnNext(newLocation),我看到它不断被触发。

我做错了什么?

[编辑]

好的,我可以看到出了什么问题,代码(我不仅仅是从中学习它),使用了DistinctUntilChanged()。我假设,从简单的阅读,这会停止向用户提供相同的价值?所以我正在使用它,位置跟踪,如果手机处于相同的位置,GeoCoordinate没有改变,那么将它发送给用户是毫无意义的,所以它只是阻止它吗?

1 个答案:

答案 0 :(得分:3)

我怀疑问题已在评论中得到解答(即如果您想要位置,即使用户没有移动,也要删除DistinctUntilChanged)。然而,这个问题有些令人烦恼 - 它使用的是Rx,但并不是特别有效。

首先,有一种更简单的方法可以将事件转换为可观察事件(这反过来又使它们更易于使用):

var watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.Default) { MovementThreshold = 0 };  
var geo = Observable.FromEventPattern<GeoPositionChangedEventArgs<GeoCoordinate>>(
                               ev => watcher.PositionChanged += ev, 
                               ev => watcher.PositionChanged -= ev)
                    .Select(ev => ev.EventArgs.Position);

然后,要获得更改,不需要那些命令性的代码。就这样做:

var changes = geo.Where(pos => (DateTime.Now - pos.Timestamp.DateTime) < locationTimeout)
                 .Select(pos => pos.Location)
                 .DistinctUntilChanged();

(当然,您可以删除DistinctUntilChanged,但不在您发布的代码中。

现在您可以直接使用changes

changes.Subscribe(loc =>
{
   PlotLine.Locations.Add(pos);
   bingMap.SetView(pos, 15);
});

没有必要管理一个真正影响一系列事件的主题。只需将事件转换为Observables即可。然后因为你一直在使用Observables,所以你可以访问许多组合器,这些组合器可以让你比现在做更多的事情。