Search code examples
system.reactiverx.net

Rx.Net How can I emit an element when a source sequence has been idle for a time?


I want to create a sequence that emits a value (let's say 'true') whenever a source sequence emits a value. Then, when the source sequence is idle for a period of time, emits 'false'. Essentially, I need to know when the source sequence is 'idle' for some time.

Source: ---1-----5-------2-------(timeout)--------8-----3------>  
           |     |       |       |                |     |  
Output: ---true--true----true----false------------true--true--->  

In actual fact, I don't need the repeated occurrences of true, so this would be even better:

Source: ---1-----5-------2-------(timeout)---------8-----3------>
           |                     |                 |
Output: ---true------------------false-------------true--------->

I've seen this answer, but to be honest I don't really understand how it's working. It seems like there should be a simpler answer.

What's worse is that I'm sure I have solved this exact problem before, but I can't remember how! Can anyone help out here?


Solution

  • It's quite simple with a Switch. Try this:

    var source = new Subject<int>();
    
    var query =
        source
            .Select(x =>
                Observable
                    .Timer(TimeSpan.FromSeconds(1.0))
                    .Select(y => false)
                    .StartWith(true))
            .Switch();
            
    query.Subscribe(Console.WriteLine);
    
    source.OnNext(1);
    Thread.Sleep(TimeSpan.FromSeconds(0.5));
    source.OnNext(5);
    Thread.Sleep(TimeSpan.FromSeconds(0.5));
    source.OnNext(2);
    Thread.Sleep(TimeSpan.FromSeconds(1.5));
    source.OnNext(8);
    Thread.Sleep(TimeSpan.FromSeconds(0.5));
    source.OnNext(3);
    

    That gives me:

    True
    True
    True
    False
    True
    True
    False