【问题标题】:WP7 - Using RX, Subscribe only triggering once but OnNext() always triggering?WP7 - 使用 RX,订阅只触发一次但 OnNext() 总是触发?
【发布时间】:2012-05-16 06:13:03
【问题描述】:

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

【问题讨论】:

  • 有关这两个代码 sn-ps 如何关联的一些上下文将有所帮助。第一个 sn-p 是第二个中引用的 MyLocation.StartGettingLocations 吗?
  • 很抱歉,我在下班前迅速提出了一些问题。如果您可以从 EDIT 中看到我知道问题只需要了解它。
  • @Gaz98:你是对的。除非值已更改,否则它不会将新值推送给观察者。删除 .DistinctUntilChanged() 行为将导致将相同的值推送给观察者。

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


【解决方案1】:

我怀疑问题已在 cmets 中得到解答(即,如果您想要位置,即使用户没有移动,也可以删除 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,所以您可以访问许多组合器,这些组合器可以让您做的比现在更多。

【讨论】:

  • 哇,为此欢呼!我将尝试使用此代码来查看我是否遵循,再次感谢。
猜你喜欢
  • 2019-09-22
  • 2020-03-15
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
相关资源
最近更新 更多