发出一个observable只有当其他发出一些值
我正在写一种监视指定远程机器的监视工具。 它会检索机器是否启动,IIS是否在那里运行以及一些参数。
机器的加/减状态可以监控,比如说3分钟。 并且IIS状态可以每〜1分钟监视一次。
如果其中一些参数发生变化,它将记录变化(DistinctUntilChanged
),如果它保持不变,它将不会执行任何操作。发出一个observable只有当其他发出一些值
我为机器状态创建了一个observable,为IIS状态创建了一个observable。 显然,如果机器停机(无需拨打GetIisState
),则无需监控任何其他远程参数。
所以,我试图使用SkipUntil
和TakeUntil
- 尝试排序暂停IisObservable
机器停机时。 但它不工作,因为我希望它。
这里是我的机器状态观察到:
machineStateObservable = Observable.Interval(TimeSpan.FromSeconds(180))
.StartWith(-1)
.Select(async it => new {Order = it, State = await GetMachineStateAsync(machine)})
.Switch()
.Do(it =>
{
if (it.Order == -1) // write initial state 1st time
{
var state = it.State ? "up" : "down";
var msg = $"{machine.Name}: Machine initial state: {state}";
Log.Info(msg);
}
})
.Select(it => it.State);
machineStateObservable
.DistinctUntilChanged()
.Buffer(2, 1).Where(it => it.Count == 2)
.Subscribe(it => Log.Info($"{machine.Name}: MachineState got changed from {it[0]} to: {it[1]}")
, ex => Log.Error(ex, "Unhandled exception!"));
我应该如何界定IisObservable
,它不会发出通知(因此不会叫GetIisState
),而machineStateObservable
是表明机器是跌?
更新:
这是我来到与@Enigmativity的帮助解决方案:
IisStateObservable = MachineStateObservable
.Select(state => state
? Observable.Interval(TimeSpan.FromSeconds(2)).StartWith(0)
.SelectMany(it => Readings.GetServiceStateAsync())
: Observable.Never<string>())
.Switch()
.Publish();
下面是创建一个可观察到的,只有当另一个可观测产生true
发出的基本格局,而不是当它产生false
。
void Main()
{
var states = new Subject<bool>();
IObservable<int> query =
states
.Select(state => state
? Observable.FromAsync(() => GetStatusAsync())
: Observable.Never<int>())
.Switch();
}
public async Task<int> GetStatusAsync()
{
return await Task.Factory.StartNew(() => 42);
}
下面的代码我建议定期调用。
void Main()
{
var states = new Subject<bool>();
IObservable<int> query =
(
from n in Observable.Interval(TimeSpan.FromMinutes(1.0))
from ms in Observable.FromAsync(() => GetMachineStateAsync())
select ms
? Observable.FromAsync(() => GetStatusAsync())
: Observable.Never<int>()
).Switch();
}
public async Task<int> GetStatusAsync()
{
return await Task.Factory.StartNew(() => 42);
}
public async Task<bool> GetMachineStateAsync()
{
return await Task.Factory.StartNew(() => true);
}
,或者,根据建议的答案。
void Main()
{
var states = new Subject<bool>();
IObservable<int> query =
states
.Select(state => state
? Observable
.Interval(TimeSpan.FromSeconds(2.0))
.StartWith(-1L)
.SelectMany(n =>
Observable.FromAsync(() => GetStatusAsync()))
: Observable.Never<int>())
.Switch();
}
public async Task<int> GetStatusAsync()
{
return await Task.Factory.StartNew(() => 42);
}
这是很好的代码,我会用它。 但是,当机器启动时,我需要调用GetStatusAsync并继续每隔1分钟调用一次,而不是一次。 – IgorStack
@IgorStack - 是的,这很简单 - 用'Observable.Interval(TimeSpan.FromMinutes(1.0))'开始整个事情,但是你可能会调用一个'GetStateAsync'来获取你的状态值。 – Enigmativity
@IgorStack - 我看了你的答案。我会使用'.SelectMany'而不是'.Select(...)'/'.Switch()' - 你的风险不会在开关方法中获得任何价值。 – Enigmativity
调用'GetIisState'在哪里? – Enigmativity
这是异步方法返回IIS状态 – IgorStack