C# 无功延长定时器/间隔重置

C# 无功延长定时器/间隔重置,c#,system.reactive,C#,System.reactive,我有一个项目,我需要每10秒发送一个状态消息,除非在此期间有更新。也就是说,每次更新时,计时器都会重置 var res = Observable .Interval(TimeSpan.FromSeconds(10)) .Where(_ => condition); res.Subscribe(_ => Console.WriteLine("Status sent.")); 现在我知道“Where”只会在计时器结束时应用,所以它没有帮助。但是,我想知道是否有办法重置间隔;或

我有一个项目,我需要每10秒发送一个状态消息,除非在此期间有更新。也就是说,每次更新时,计时器都会重置

var res = Observable
  .Interval(TimeSpan.FromSeconds(10))
  .Where(_ => condition);

res.Subscribe(_ => Console.WriteLine("Status sent."));

现在我知道“Where”只会在计时器结束时应用,所以它没有帮助。但是,我想知道是否有办法重置间隔;或者使用带重复的计时器()。

使用标准的Rx操作符,这非常容易实现

你的问题中不清楚的是什么是“更新”。我将假设您有某种类型的可观察对象,每次更新都会触发,或者您可以创建一个主题,当有更新时,您将调用
.OnNext(…)
。没有可观察的更新,很难知道何时重置计时器

下面是代码:

var update = new Subject<bool>();

var res =
    update
        .Select(x => Observable.Interval(TimeSpan.FromSeconds(10.0)))
        .Switch();

res
    .Subscribe(_ => Console.WriteLine("Status sent."));

update.OnNext(true);

这很好-它仍然可以工作,但是对于每个计时器,触发
res
将创建一个新的计时器。这将意味着任何依赖于你的
更新的
可观察/主题的东西仍然可以正常工作。

我认为你也可以在这里使用油门。节流的目的是,如果在给定的时间间隔内收到另一个元件,则不会让元件通过。因此,在您的情况下,如果在10秒内收到更新消息,则不要发送状态。请参阅下面的单元测试,它使用200个刻度作为节流周期

[TestMethod]
    public void Publish_Status_If_Nothing_Receieved()
    {
        //Arrange
        var scheduler = new TestScheduler();
        var statusObserver = scheduler.CreateObserver<Unit>();
        var updateStream = scheduler.CreateColdObservable(OnNext(100, 1), OnNext(200, 2), OnNext(600, 3),
            OnNext(700, 4));

        var waitTime = TimeSpan.FromTicks(200);

        //Act
        updateStream.Throttle(waitTime, scheduler)
            .Select(_ => Unit.Default)
            .Subscribe(statusObserver);

        //Verify no status received
        scheduler.AdvanceTo(100);
        Assert.AreEqual(0, statusObserver.Messages.Count);

        //Verify no status received
        scheduler.AdvanceTo(200);
        Assert.AreEqual(0, statusObserver.Messages.Count);

        //Assert status received
        scheduler.AdvanceTo(400);
        statusObserver.Messages.AssertEqual(OnNext(400, Unit.Default));

        //Verify no more status received
        scheduler.AdvanceTo(700);
        statusObserver.Messages.AssertEqual(OnNext(400, Unit.Default));
    }
[TestMethod]
public void Publish_Status_If_Nothing_received()
{
//安排
var scheduler=newtestscheduler();
var statusObserver=scheduler.CreateObserver();
var updateStream=scheduler.CreateColdObservable(OnNext(100,1)、OnNext(200,2)、OnNext(600,3),
OnNext(700,4));
var waitTime=TimeSpan.FromTicks(200);
//表演
updateStream.Throttle(等待时间,调度程序)
.Select(=>Unit.Default)
.订阅(状态观察员);
//验证未收到任何状态
高级调度程序(100);
Assert.AreEqual(0,statusObserver.Messages.Count);
//验证未收到任何状态
高级调度程序(200);
Assert.AreEqual(0,statusObserver.Messages.Count);
//断言已收到状态
高级调度员(400);
statusObserver.Messages.AssertEqual(OnNext(400,Unit.Default));
//确认没有收到更多的状态
AdvanceTo(700);
statusObserver.Messages.AssertEqual(OnNext(400,Unit.Default));
}

我随身带着这个小助手方法:

public static IObservable<long> CreateAutoResetInterval<TSource>(IObservable<TSource> resetter, TimeSpan timeSpan, bool immediate = false)
{
    return resetter.Select(_ => immediate ? Observable.Interval(timeSpan).StartWith(0) : Observable.Interval(timeSpan)).Switch();
}
public static IObservable CreateAutoResetInterval(IObservable重置器,TimeSpan TimeSpan,bool immediate=false)
{
返回resetter.Select(=>immediate?Observable.Interval(timeSpan).StartWith(0):Observable.Interval(timeSpan)).Switch();
}

它基本上与Enigmativity的答案相同

非常干净的实现。我使用它作为“注销”计时器,如果状态在一段时间内没有改变,它依赖于Redux存储(即流)触发注销。正是这种东西让Rx使用起来如此有趣。
public static IObservable<long> CreateAutoResetInterval<TSource>(IObservable<TSource> resetter, TimeSpan timeSpan, bool immediate = false)
{
    return resetter.Select(_ => immediate ? Observable.Interval(timeSpan).StartWith(0) : Observable.Interval(timeSpan)).Switch();
}