2

我想在五秒钟内每秒尝试一次,如果它们都是假的,则返回假,并在第一次为真时返回真。当务之急,它看起来像这样:

bool TryFiveTimes()
{
    for (int i = 0; i < 5; i++)
    {
        if (Fn())
            return true;
        System.Threading.Thread.Sleep(1000);
    }
    return false;
}

我想使用 Rx 来做到这一点,但想不出一个简洁的方法。我目前的尝试是:

bool TryFiveTimes()
{
    return Observable.Interval(TimeSpan.FromSeconds(1))
        .Take(5)
        .Select(_ => Fn())
        .Scan(false, (curr, prev) => curr || prev)
        .Last();
}

Fn()这将给出正确的结果,但如果在结束前返回 true ,则不会提前返回。

4

2 回答 2

3

对于您的实现,只需使用.First()方法而不是.Last()

    static bool TryFiveTimes()
    {
        return Observable.Interval(TimeSpan.FromSeconds(1))
            .Take(5)
            .Select(_ => Fn())
            .Scan(false, (curr, prev) => curr || prev)
            .FirstOrDefault(v => v);
    }

    static int counters = 0;
    static bool Fn()
    {
        counters++;
        Console.WriteLine(counters);
        return counters > 2;
    }

[编辑]:添加的代码将证明该Fn方法只会在它第一次返回之前执行True

此外,您在这里并不需要Scan(),较短的版本是:

    return Observable
        .Interval(TimeSpan.FromSeconds(1))
        .Take(5)
        .Select(_ => Fn())
        .FirstOrDefault(v => v);
于 2013-01-11T07:36:49.903 回答
2

您可以尝试使用ConcatwithReturn像这样:

bool TryFiveTimes()
{
    return Observable
        .Interval(TimeSpan.FromSeconds(1))
        .Take(5)
        .Select(_ => Fn())
        .Where(x => x)
        .Concat(Observable.Return(false))
        .First();
}
于 2013-01-11T10:37:25.477 回答