加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 使用Reactive Extensions轮询Web服务并绑定最后的x个结果

发布时间:2020-12-15 07:53:39 所属栏目:百科 来源:网络整理
导读:我正在尝试将Reactive Extensions(Rx)用于一个看起来很合适的任务,以特定间隔轮询Web服务并显示其最后的x结果. 我有一个Web服务,它向我发送我想要监视的工具的状态.我想以特定的速率轮询此工具,并在列表中显示已轮询的最后20个状态. 所以我的列表就像是服务
我正在尝试将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;
    }
}

在视图中,我只有一个绑定到CurrentTime属性的标签和一个绑定到Times属性的列表.

我的问题是:

>它不仅限于列表中的20个项目,因为我总是向ObservableCollection添加项目,但我找不到更好的数据绑定方法
> Interval不能像我想的那样工作.如果查询运行时间超过1秒,则将同时运行两个查询,我不希望这样做.我的目标是查询无限期地重复,但每秒的查询速度不超过1次.如果查询结束时间超过1秒,则应等待它完成并直接触发新查询.

第二次编辑:

下面的编辑是我愚蠢而且非常困惑,它会不断触发事件,因为Interval是一个永远不会结束的事物.布兰登的解决方案是正确的,并按预期工作.

编辑:

根据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))

我可以看到对控制台的写入每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;
    });

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读