Gim*_*mly 7 c# system.reactive
我正在尝试将Reactive Extensions(Rx)用于一个看似合适的任务,以特定间隔轮询Web服务并显示其最后的x结果.
我有一个Web服务,它向我发送我想要监视的工具的状态.我想以特定的速率轮询此工具,并在列表中显示已轮询的最后20个状态.
所以我的列表就像是服务结果的"移动窗口".
我正在使用Caliburn.Micro开发一个WPF应用程序,但我不认为这是非常相关的.
我到目前为止得到的是以下内容(只是我快速入侵的示例应用程序,我不打算在真实应用程序中的ShellViewModel中执行此操作):
public class ShellViewModel : Caliburn.Micro.PropertyChangedBase, IShell
{
private ObservableCollection<string> times;
private string currentTime;
public ShellViewModel()
{
times = new ObservableCollection<string>();
Observable
.Interval(TimeSpan.FromSeconds(1))
.SelectMany(x => this.GetCurrentDate().ToObservable())
.ObserveOnDispatcher()
.Subscribe(x =>
{
this.CurrentTime = x;
this.times.Add(x);
});
}
public IEnumerable<string> Times
{
get
{
return this.times;
}
}
public string CurrentTime
{
get
{
return this.currentTime;
}
set
{
this.currentTime = value;
this.NotifyOfPropertyChange(() => this.CurrentTime);
}
}
private async Task<string> GetCurrentDate()
{
var client = new RestClient("http://www.timeapi.org");
var request = new RestRequest("/utc/now.json");
var response = await client.ExecuteGetTaskAsync(request);
return response.Content;
}
}
Run Code Online (Sandbox Code Playgroud)
在视图中,我只有一个绑定到CurrentTime
属性的标签和一个绑定到Times
属性的列表.
我的问题是:
ObservableCollection
但我找不到更好的数据绑定方式第二次编辑:
下面的编辑是我愚蠢而且很困惑,它会不断触发事件,因为Interval是一种永不停止的东西.Brandon的解决方案是正确的,并按预期工作.
编辑:
根据Brandon的例子,我尝试在LinqPad中执行以下代码:
Observable
.Merge(Observable.Interval(TimeSpan.FromSeconds(2)), Observable.Interval(TimeSpan.FromSeconds(10)))
.Repeat()
.Scan(new List<double>(), (list, item) => { list.Add(item); return list; })
.Subscribe(x => Console.Out.WriteLine(x))
Run Code Online (Sandbox Code Playgroud)
我可以看到对控制台的写入每2秒发生一次,而不是每10次发生一次.因此重复不会等待Observable在重复之前完成.
试试这个:
// timer that completes after 1 second
var intervalTimer = Observable
.Empty<string>()
.Delay(TimeSpan.FromSeconds(1));
// queries one time whenever subscribed
var query = Observable.FromAsync(GetCurrentDate);
// query + interval timer which completes
// only after both the query and the timer
// have expired
var intervalQuery = Observable.Merge(query, intervalTimer);
// Re-issue the query whenever intervalQuery completes
var queryLoop = intervalQuery.Repeat();
// Keep the 20 most recent results
// Note. Use an immutable list for this
// https://www.nuget.org/packages/microsoft.bcl.immutable
// otherwise you will have problems with
// the list changing while an observer
// is still observing it.
var recentResults = queryLoop.Scan(
ImmutableList.Create<string>(), // starts off empty
(acc, item) =>
{
acc = acc.Add(item);
if (acc.Count > 20)
{
acc = acc.RemoveAt(0);
}
return acc;
});
// store the results
recentResults
.ObserveOnDispatcher()
.Subscribe(items =>
{
this.CurrentTime = items[0];
this.RecentItems = items;
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1331 次 |
最近记录: |