C# 如何使用Interval作为计时器来检查webAPI服务并返回可观察的新值序列

C# 如何使用Interval作为计时器来检查webAPI服务并返回可观察的新值序列,c#,system.reactive,C#,System.reactive,所以,在我看来这很简单。我想使用Interval作为计时器,每秒检查一次WebAPI服务,然后使用Distinct对其进行过滤,这样我只会在添加新值时收到通知 (ed.我想在前面强调一下,我正在使用.Net的反应式扩展,这就是这些术语的来源,Interval(…)和Distinct()) 在实现方面,我有一个异步函数,它返回一个任务,其中后解调是非常简单的虚拟模型: public class PostalCodeModel { public int PostalCode { get; s

所以,在我看来这很简单。我想使用Interval作为计时器,每秒检查一次WebAPI服务,然后使用Distinct对其进行过滤,这样我只会在添加新值时收到通知

(ed.我想在前面强调一下,我正在使用.Net的反应式扩展,这就是这些术语的来源,
Interval(…)
Distinct()

在实现方面,我有一个异步函数,它返回一个
任务
,其中
后解调
是非常简单的虚拟模型:

public class PostalCodeModel
{
    public int PostalCode { get; set; }
    public string City { get; set; }

    public PostalCodeModel(int code, string name)
    {
        this.PostalCode = code;
        this.City = name;
    }

    public override string ToString()
    {
        return string.Format("{0} = {1}", PostalCode, City);
    }
}
在我的测试应用程序中,到目前为止,我已经能够找出如何创建间隔计时器:

var interval = Observable.Interval(TimeSpan.FromSeconds(1));
并在异步方法上使用
ToObservable()

///Bad!
private static IObservable<PostalCodeModel[]> CheckPostalCodes()
{
    using (ApiClient client = new ApiClient("http://localhost:55457"))
    {
        return client.GetPostalCodesAsync().ToObservable();
    }
}

//Good, thanks Enigmativity!
private static IObservable<PostalCodeModel[]> CheckPostalCodes()
{
    return Observable.Using(
        () => new ApiClient("http://localhost:55457"),
        client => client.GetPostalCodesAsync().ToObservable())
        .Take(1);
}
理想情况下,我会这样做:

// No workie :(
Observable.Interval(TimeSpan.FromSeconds(1)).CheckPostalCodes().Distinct()
或者类似的,但我不知道怎么做。即使这是个好主意。最终,这个输出需要指示GUI中的更改。我甚至不确定在对象数组中使用Distinct是否能按我期望的方式工作(只知道数组中是否有新值)


正如我在下面对
Enigmativity
s答案的评论中所指出的,在按照他的建议更正了
CheckPostalCodes()
之后,订阅非常简单,但是我确实需要向Distinct调用添加一个keySelector,以便它能够正确确定返回的数组是否相同。我认为仅使用
array.Count()
就足以满足我们的目的,即:

        var query = Observable
                        .Interval(TimeSpan.FromSeconds(1))
                        .SelectMany(_ => CheckPostalCodes())
                        .Distinct(array => array.Count());

您错误地编写了
CheckPostalCodes
方法。
using
语句在任何可观察对象订阅之前就已经很好地完成了。您需要使用
可观察。请改用
方法

另外,如果您只希望API调用返回一个值,请不要忘记添加一个
。使用(1)
,以确保在一个返回值之后,可观察的停止

因此,
CheckPostalCodes
应该如下所示:

private static IObservable<PostalCodeModel[]> CheckPostalCodes()
{
    return
        Observable
            .Using(
                () => new ApiClient("http://localhost:55457"),
                client => client.GetPostalCodesAsync().ToObservable())
            .Take(1);
    }
}

让我知道这是否对您有效。

这可以创建序列,但正如我担心的那样,Distinct不会“深入比较”数组,我会得到一个相同数组值的重复序列,即订阅:
query.Subscribe(数组=>Console.WriteLine($”{DateTime.Now}{string.Join(,,(object[])array})
我重复了一些类似的内容:
11.5.2017 13:15:36 110=Name1,210=Name2 11.5.2017 13:15:37 110=Name1,210=Name2
我想知道我是否需要做一个比较器,如下面的答案:-或者数组的某个地方存在比较器吗?实际上,我想这就足够了,由于我们在另一端控制向数组添加的内容/方式:
var query=Observable.Interval(TimeSpan.FromSeconds(1)).SelectMany(=>CheckPostalCodes()).Distinct(array=>array.Count())你能解释为什么需要Take(1)吗?如果没有包含它,会不会有内存泄漏?另外,处理异步调用中的错误的最佳/正确方法是什么,即如果服务超时或返回OK以外的任何内容(毕竟是HTTP服务)?
private static IObservable<PostalCodeModel[]> CheckPostalCodes()
{
    return
        Observable
            .Using(
                () => new ApiClient("http://localhost:55457"),
                client => client.GetPostalCodesAsync().ToObservable())
            .Take(1);
    }
}
var query =
    Observable
        .Interval(TimeSpan.FromSeconds(1.0))
        .SelectMany(n => CheckPostalCodes())
        .Distinct();