我正在使用我正在制作的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
}
);;
编辑:不,它不起作用
答案 0 :(得分:2)
RX中有一些不同的速率限制运算符。 Sample
与您描述的内容最接近,但如果源未生成新通知,则不会每5秒生成一次通知(换句话说:Sample =“不会超过”)。
您应该能够通过组合其他几个运算符来获得轮询效果。首先,我们需要Interval
来获取标记,并CombineLatest
在标记处进行采样。但是,CombineLatest将输出来自原始来源的刻度和通知的结果。为了解决这个问题,我们可以结合使用Scan
,Where
和Select
。最后你应该有:
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;