.net 4.0 使用反应式扩展和计时器&引用;“为假人而设”;版本
尽管社区提供了耐心的帮助,而且——我担心我还没有接近真正的理解。我正试图将这些概念灌输到我的大脑中,但我想解释一下亚瑟王的话:“这项新的研究让我困惑。请再解释一下关于羊的膀胱和地震。”在我看来,这正是我们可能正在谈论的 我将把它简化为需求(已经发生了变化,.NET 4.0是关键),而不是用我自己的(可能有缺陷的)实现走上错误的道路:.net 4.0 使用反应式扩展和计时器&引用;“为假人而设”;版本,.net-4.0,system.reactive,reactive-programming,.net 4.0,System.reactive,Reactive Programming,尽管社区提供了耐心的帮助,而且——我担心我还没有接近真正的理解。我正试图将这些概念灌输到我的大脑中,但我想解释一下亚瑟王的话:“这项新的研究让我困惑。请再解释一下关于羊的膀胱和地震。”在我看来,这正是我们可能正在谈论的 我将把它简化为需求(已经发生了变化,.NET 4.0是关键),而不是用我自己的(可能有缺陷的)实现走上错误的道路: 我需要使用.NET Framework 4.0来编写Windows服务 我需要我的Windows服务来调用web服务(WS),并将一个URL传递给它,但每次调用只传
Observable.Timer
s,但是如何在出现错误时禁用计时器呢?这可能是一个等待发生的CancellationToken
(或者我只是完成计时器),但我似乎无法将这些示例混合到一个可靠的、可理解的解决方案中
有人想牵着这位老人的手,用小词解释做这种胡说八道的正确方法吗?如果我没有很好地解释它,或者如果我遗漏了什么,我会很乐意编辑它
谢谢。1)我想你应该看看可观察的间隔<代码>可观察。计时器
是一个单值序列,与之相反,可观察。间隔
将在给定的间隔内持续产生值。如果对于每个项目/url,该轮询周期是恒定的,那么这可能就是您想要的
2) 您可以将IEnumerable
(URL)和IObservable
(轮询事件)序列混合在一起
3) 错误将终止序列。您可以通过将序列中的值投影(Select
)到WebRequest的输出来利用这一点。如果WebRequest失败,序列将OnError
,异常将作为OnError负载传播
慢慢地通过这个过程
- 我们要获取URL/句点对的列表
- 在给定的时间段轮询URL
- 如果对某个URL的任何调用失败,请停止轮询该URL(并可能记录该URL)
- 如果windows服务已停止,请停止轮询
protected override void OnStart(string [] args)
{
var resource = new {Url="http://www.bing.com", Period=TimeSpan.FromMinutes(3)};
var pollingSequence = Observable.Interval(resource.Period)
.Select(_=>Request(resource.Url));
var subscription = pollingSequence.Subscribe(
response=>Log(response),
ex=>Log(ex)
));
_subscriptions = new CompositeDisposable(subscription);
}
protected override void OnStop()
{
Dispose();
}
private bool Request(string url)
{
//TODO:
}
public void Dispose()
{
_subscriptions.Dispose();
}
为了将其可视化,我们可以使用“大理石图”。这里每个字符空间代表1分钟。OnNext表示为“o”(大理石)
更准确地说,我们实际上是通过事件获取值(尽管我们忽略了值)
然后,我们将每个事件投影到一个请求,因此序列现在转到这里(其中“r”表示来自请求的响应)
如果任何请求失败,序列将终止。例如,这里3个请求失败,我们显示一个带有“X”的OnError
bing --r--r--X
现在我们可以将示例扩展到资源列表,即IEnumerable
接下来,我们考虑每一行也有轮询事件序列(时间数据)。根据上述代码(使用1个字符=1分钟)
- 您不能订阅
,但有处理此类数据的接收方法,如Concat和Merge。 但是,我们不想使用这些,因为它们将序列展平为单个序列,这意味着如果任何序列失败,所有轮询都将停止IEnumerable
n
会有多大?@Brandon-n
在我最疯狂的极端情况下不应该超过100个URL-最多可能是10个或20个。那么,Lee的解决方案就是这样。Lee,你太好了。感谢您花额外的时间为班上速度较慢的孩子解释这一点。;-)你能为轮询序列分解LINQ查询吗?我在概念化select
和.select()
一起工作的方式时遇到问题。我已更新示例,以显示首先使用单个资源,然后扩展该示例使用资源列表。你是个了不起的老师。这太棒了,我希望它能像帮助我一样帮助社区的其他人。再次感谢。这段代码仍然“失败”,程序几乎立即停止。订阅新CompositeDisposable(订阅)
不应该阻止这种情况发生吗?
bing --0--1--2--3-
bing --r--r--r--r-
bing --r--r--X
protected override void OnStart(string [] args)
{
var resources = new[] {
new {Url="http://www.bing.com", Period=TimeSpan.FromMinutes(3)},
new {Url="http://www.google.com", Period=TimeSpan.FromMinutes(2)},
new {Url="http://www.yahoo.com", Period=TimeSpan.FromMinutes(5)},
new {Url="http://www.stackoverflow.com", Period=TimeSpan.FromMinutes(2)}
};
//The same as before, but now we create a polling sequence per resource.
var pollingSequences = from resource in resources
select Observable.Interval(resource.Period)
.Select(_=>Request(resource.Url));
//Now we cant subscribe to an `IEnumerable<IObservable<T>>` *,
// but we can subscribe to each sequence in it.
// This turns our queries (IE<IO<T>>) into subscriptions (IE<IDisposable>).
var subscriptions = pollingSequences.Select(x =>
x.Subscribe(
response=>Log(response),
ex=>Log(ex)
));
_subscriptions = new CompositeDisposable(subscriptions);
}
bing
google
yahoo
SO
bing --1--2--3- (every 3rd minute)
google -1-2-3-4-5 (every 2nd minute)
yahoo ----1----2 (every 5 minutes)
SO -1-2-3-4-5 (every 2nd minute)