用Rx尝试5次



我想在五秒钟内每秒钟尝试一些东西,如果它们都为假则返回false,第一次为真则返回true。命令式地,它看起来像这样:

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,则不会提前返回。

对于您的实现只需使用.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;
    }

[EDIT]:添加代码,证明Fn方法将只在第一次返回True之前执行

同样,这里也不需要Scan(),更短的版本是:

    return Observable
        .Interval(TimeSpan.FromSeconds(1))
        .Take(5)
        .Select(_ => Fn())
        .FirstOrDefault(v => v);

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

bool TryFiveTimes()
{
    return Observable
        .Interval(TimeSpan.FromSeconds(1))
        .Take(5)
        .Select(_ => Fn())
        .Where(x => x)
        .Concat(Observable.Return(false))
        .First();
}

相关内容

  • 没有找到相关文章

最新更新