繁体   English   中英

使用RX在间隔后获取当前位置

[英]Get the current location after an interval using RX

我在我正在制作的wp7应用程序中使用了反应式扩展,我希望以一定的间隔获取当前位置(间隔基于用户设置)。 对于这个例子,我们可以说每5秒后我想知道GeoCoordinateWatcher的当前位置。

我已经阅读了一些我可以使用的地方。延迟(5秒)但是这不会只是延迟位置变化的流程吗? 因为我只是在当前位置之后,会.Delay(5秒).Last()为我想要的工作吗?

我的代码到目前为止

if (LocationServices == null)
     LocationServices = new GeoCoordinateWatcher(GeoPositionAccuracy.High)
     {
        MovementThreshold = 2
     };

// Take the first ready status from the GeoCoordinateWatcher
var status = (from o in Observable.FromEvent<GeoPositionStatusChangedEventArgs>                  LocationServices, "StatusChanged")
              where o.EventArgs.Status == GeoPositionStatus.Ready
              select o);

status.Subscribe();

var pos = (from s in status
           from p in Observable.FromEvent<GeoPositionChangedEventArgs<GeoCoordinate>>(LocationServices, "PositionChanged")
           select p.EventArgs.Position); // Do something here to delay?

        pos.Subscribe(LastPos =>
        {
            // Do something with LastPos
        }
        );

        LocationServices.Start();

我觉得这样的事情会起作用吗?

var pos = (from s in status
           from p in Observable.FromEvent<GeoPositionChangedEventArgs<GeoCoordinate>>(LocationServices, "PositionChanged")
           select p.EventArgs.Position).Delay( var pos = (from s in status
                   from p in Observable.FromEvent<GeoPositionChangedEventArgs<GeoCoordinate>>(LocationServices, "PositionChanged")
                   select p.EventArgs.Position).TakeLast(1).Delay(new TimeSpan(0,0,5));

        pos.Subscribe(Lastpos =>
        {
           // Do something with Lastpos 
        }
        );;           

编辑:不,它不起作用

RX中有一些不同的速率限制运算符。 Sample与您描述的内容最接近,但如果源未生成新通知,则不会每5秒生成一次通知(换句话说:Sample =“不会超过”)。

您应该能够通过组合其他一些运算符来获得轮询效果。 首先,我们需要Interval来获取刻度,而CombineLatest需要在刻度CombineLatest进行采样。 但是,CombineLatest将输出来自原始来源的刻度和通知的结果。 为了解决这个问题,我们可以结合使用ScanWhereSelect 最后你应该有类似的东西:

IObservable<T> Poll<T>(this IObservable<T> source, TimeSpan interval)
{
    //error checking goes here
    return source.CombineLatest(Observable.Interval(interval),
                                Tuple.Create)
                 .Scan(Tuple.Create(string.Empty, -1L, -1L),
                       (a, t) => Tuple.Create(t.Item1, t.Item2, a.Item2))
                 .Where(t => t.Item2 != t.Item3)
                 .Select(t => t.Item1);
}

关于您发布的代码的一些注意事项:

var pos = (from s in status
           from p in Observable.FromEvent<GeoPositionChangedEventArgs<GeoCoordinate>>(LocationServices, "PositionChanged")
           select p.EventArgs.Position);

每次将状态事件触发为就绪时,这将对PositionChanged事件进行新的订阅。 这最终会导致多次报告位置变化,这可能不是您想要的。 你可能想要更像的东西:

var status = Observable.FromEvent<...>(LocationServices, "StatusChanged");
var readys = status.Where(o => o.EventArgs.Status == GeoPositionStatus.Ready);
var notReadys = status.Where(o => o.EventArgs.Status != GeoPositionStatus.Ready);
var positions = Observable.FromEvent<...>)(LocationServices, "PositionChanged");

var readyPositions = from r in readys
                     from p in positions.TakeUntil(notReadys)
                     select p;
//now you can use the Poll operator
readyPositions = readyPositions.Poll(TimeSpan.FromSeconds(5));

编辑在进一步审查后,如果您想要做的就是经常轮询该职位,则无需处理任何一个事件。 您只需检查计时器上的属性即可。

var readyPositions = from tick in Observable.Interval(TimeSpan.FromSeconds(5))
                     where LocationServices.Status == GeoPositionStatus.Ready
                     select LocationServices.Position;

如果您只想在观察者处于“就绪”状态时运行计时器,则可以使用状态事件,但仍然不需要使用位置事件。

//using variable definitions from above (readys, notReadys)
var readyPositions = from r in readys
                     from i in Observable.Interval(TimeSpan.FromSeconds(5))
                                         .TakeUnitl(notReadys)
                     select LocationServices.Position;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM