我有一个web服务,我希望在布尔值设置为true后立即查询更新,然后每5分钟重新检查一次。
这是我目前的观察结果:
_queryDisposable = Observable
.Interval(TimeSpan.FromMinutes(5))
.ObserveOn(Scheduler.ThreadPool)
.Where(i => IsProcessing) // IsProcessing is the bool value
.Subscribe(GetFeeds, OnError, OnComplete);
这个观察者将检查IsProcessing
bool是否每5分钟为真或假,然后如果为真则调用GetFeeds
。
我能想到达到预期效果的唯一方法是使IsProcessing
成为属性支持的字段,并使用以下两个可观察对象进行处理:
private bool _isProcessing;
public bool IsProcessing
{
get { return _isProcessing; }
set
{
if (_isProcessing == value)
return;
_isProcessing = value;
if (!value)
{
if(_queryDisposable != null)
_queryDisposable.Dispose();
_queryDisposable = null;
}
else
{
Observable
.Range(0,1)
.ObserveOn(Scheduler.ThreadPool)
.Subscribe(GetFeedsSafe, OnError, OnComplete);
_queryDisposable = Observable
.Interval(TimeSpan.FromMinutes(5))
.ObserveOn(Scheduler.ThreadPool)
.Subscribe(GetFeedsSafe, OnError, OnComplete);
}
}
}
我不认为这是一个非常优雅的解决方案,所以我想知道是否有更好的方法来实现这种效果?
答案 0 :(得分:3)
我是否遗漏了某些内容,或者您是否只是在启动Observable之前立即致电订阅?
Subscribe(GetFeeds, OnError, OnComplete);
// Or perhaps, if you want it to be async,
new TaskFactory().StartNew(()=>Subscribe(GetFeeds, OnError, OnComplete));
_queryDisposable = Observable
.Interval(TimeSpan.FromMinutes(5))
.ObserveOn(Scheduler.ThreadPool)
.Where(i => IsProcessing) // IsProcessing is the bool value
.Subscribe(GetFeeds, OnError, OnComplete);
编辑:Pure Rx,来自http://social.msdn.microsoft.com/Forums/sa/rx/thread/c4acaf34-3136-4206-a6f9-ef5afba74b2b:
Observable.Interval(TimeSpan.FromMinutes(5))
.StartWith(-1L)
.ObserveOn(Scheduler.ThreadPool)
.Where(i => IsProcessing) // IsProcessing is the bool value
.Subscribe(GetFeeds, OnError, OnComplete);
答案 1 :(得分:2)
要立即开始排序并在给定时间内仍然生成一个值,您有两个选项:
接下来我假设您想要在IsProcessing值设置为false时取消计时器,您还希望在将序列设置回true时重新启动序列。无论何时设置IsProcessing值,上述两个答案都会运行5分钟的间隔。如果设置IsProcessing = true,序列将启动,如果一分钟后您设置IsProcessing = false然后IsProcessing = true,您仍需要等待4分钟才能再次查询。我认为这不是你想要的?
所以我们希望这可以触发财产变更。 @SPFiredrake很好地建议INPC并将事件转换为Observable序列。周围有很多小片段可以帮助你做到这一点。假设我们使用的是一个扩展方法PropertyChanges,我们可以编写这个非常简单的查询。
var isProcessingValues = this.PropertyChanges(x=>x.IsProcessing);
isProcessingValues
.Where(isProcessing=>isProcessing)
.SelectMany(_=>
Observable.Timer(TimeSpan.Zero, TimeSpan.FromMinutes(5))
.TakeUntil(isProcessingValues.Where(isProcessing=>!isProcessing))
)
.Select(_=>GetFeeds()) //What does GetFeeds actually return?
.SubscribeOn(Scheduler.NewThread)
.Subscribe(feedData=>Console.WriteLine(feedData),
ex=>Console.WriteLine (ex),
()=>Console.WriteLine (completed));
慢慢地踩过这个:
答案 2 :(得分:0)
你有没有想过让IsProcessing变量触发一个你可以听的prop改变的事件?
var processing = Observable
.FromEventPattern<PropertyChangedEventArgs>(this, "PropertyChanged")
.Where(tr => tr.EventArgs.Property == "IsProcessing" && ((Type)tr.Sender).IsProcessing);
_queryDisposable = Observable
.Interval(TimeSpan.FromMinutes(5))
.ObserveOn(Scheduler.ThreadPool)
.And(processing) // Will only fire when both sequences have an available value.
.Subscribe(GetFeeds, OnError, OnComplete);
这也确保了如果它正在处理,它只会触发一次因为处理observable一次只提供一个值(每个IsProcessing改为true
)所以你不必担心如果它在5分钟后仍然处理,它将再次发射。