所以,在我看来,这很简单。我想使用间隔作为计时器,每秒检查一次 WebAPI 服务,然后使用 Distinct 对其进行过滤,以便仅在添加新值时收到通知。
(编.我想尽早强调我正在使用 .Net 的反应式扩展是一种很好的形式,这就是这些术语的来源,Interval(...)
和Distinct()
)。
在实现方面,我有一个异步函数,它返回一个Task<PostalCodeModel[]>
,其中PostalCodeModel
非常简单的虚拟模型:
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);
}
但是,我很难弄清楚如何将这些链接在一起以及在哪里应用 Distinct 方法,到目前为止我的尝试并不成功:
// No workie :(
var sup = interval.Subscribe(
CheckPostalCodes,
() => Console.WriteLine("Completed"));
理想情况下,我会做这样的事情:
// No workie :(
Observable.Interval(TimeSpan.FromSeconds(1)).CheckPostalCodes().Distinct()
或类似,但我不知道该怎么做。或者即使这是一个好主意。最终,它的输出需要指示 GUI 中的更改。而且我什至不确定在对象数组上使用 Distinct 是否按照我期望的方式工作(如果数组中有新值,请告诉我)。
正如我在下面对Enigmativity
答案的评论中指出的那样,在按照他的建议更正CheckPostalCodes()
后,订阅非常简单,但是我确实需要向 Distinct 调用添加一个 keySelector,以便它能够正确确定返回的数组是否相同。我认为简单地使用array.Count()
就足以满足我们的目的,即:
var query = Observable
.Interval(TimeSpan.FromSeconds(1))
.SelectMany(_ => CheckPostalCodes())
.Distinct(array => array.Count());
您编写了错误的CheckPostalCodes
方法。using
声明在任何可观察对象订阅之前就已经真正结束了。您需要改用Observable.Using
方法。
此外,如果您只期望从 API 调用中返回一个值,请不要忘记添加一个.Take(1)
以确保可观察值在一个返回值后停止。
所以CheckPostalCodes
应该是这样的:
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();
让我知道这是否适合您。