0

好的,我正在使用响应式扩展进行另一场比赛,特别是 wp7。

我正在查看 GeoCoordinateWatcher 位置更改事件,如下所示

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()。我假设,通过简要阅读,这会阻止向订阅者输出相同的价值?所以就我使用它的目的而言,位置跟踪,如果手机在同一个位置并且地理坐标没有改变,那么将它发送给用户是没有意义的,所以它只是阻止它?

4

1 回答 1

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,你可以访问许多组合器,这些组合器可以让你做比现在更多的事情。

于 2012-05-15T21:04:33.360 回答