只发出一个observable,而另一个发出一些值

时间:2017-10-10 23:47:38

标签: c# system.reactive reactive

我正在编写监控指定远程机器的监控工具。 它将检索机器是否已启动,IIS是否在那里运行以及更多参数 每隔3分钟就可以监控机器上/下状态。 每隔约1分钟就可以监控IIS状态 如果其中一些参数发生了变化,它会记录更改(DistinctUntilChanged),如果它保持不变,它就不会做任何事情。

我为机器状态创建了一个observable,为IIS状态创建了一个observable。 显然,如果机器停机,则无需监控任何其他远程参数(无需拨打GetIisState)。
所以,我尝试使用SkipUntilTakeUntil - 尝试在机器关闭时暂停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();

1 个答案:

答案 0 :(得分:1)

这里是创建一个observable的基本模式,只有当另一个observable产生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);
}