none
How to generate data on random time intervals (Observable.Generate/Interval)?

    Question

  • Hi!

    This question is related to another one I asked just frequently regarding absence of signals during some time intervals.

    I would like to generate a sequence of random time intervals. I'm currently generating some test data like so

    _dataSource = from n in Observable.Interval(TimeSpan.FromMilliseconds(100))
                              select new Data
                              {
                                  SomeData = DateTimeOffset.Now.ToString()
                              };

    but I would like to introduce some randomness and generate it more like

    _dataSource = from n in Observable.Generate(0, i => i < 10, i => ++i, i => i, _ => TimeSpan.FromSeconds(new Random().Next(300, 2000)))
                              select new Data
                              {
                                  SomeData = DateTimeOffset.Now.ToString()
                              };

    but this won't work, no new Data objects will be created. I suscpect I would need to Subscribe to the stream, but then I'm unable to form the following query, which should consume the data. Which is like so

    timer = (from duration in durations
                          select (from _ in Observable.Timer(DateTime.Now)
                                  from x in _dataSource.Throttle(maximumInactivityTime).TakeUntil(duration.end)
                                  select x)).Switch();

    It seems generating output at random intervals should be possible, but I'm currently unable to form one. I see this has to do with hot and cold observables.

    Any help will be apprciated, thanks!


    • Edited by Veksi Wednesday, October 09, 2013 6:26 AM
    Wednesday, October 09, 2013 6:25 AM

Answers

  • Hi,

    > I would like to introduce some randomness and generate it more like [snip]

    Your usage of Generate is fine, though it's a bad idea to create a new Random instance each iteration, even though in your particular usage it won't matter because of how long you're waiting between notifications.  Instead, you should create one instance of Random outside of the query and then use it within the query.

    That's unrelated to your stated problem though.

    > I suscpect I would need to Subscribe to the stream, but then I'm unable to form the following query, which should consume the data [snip]

    Generate returns a cold observable, so you must either subscribe to it directly or use it within another query, as you are doing.

    See my blog post on Hot and Cold Observables for details.

    However, I suspect that the reason you think that it's not working is simply because you expect that Generate will push the first notification immediately, though in fact it does not.  It applies the specified delay to the first element, just as is does for every other element.

    To ensure that _dataSource pushes an element immediately when an observer subscribes, either apply the StartWith operator or add a conditional to your interval algorithm.

    Here's an example of the latter:

    i => i == 0 ? TimeSpan.Zero : TimeSpan.FromSeconds(random.Next(300, 2000))

    - Dave


    http://davesexton.com/blog

    • Marked as answer by Veksi Thursday, October 17, 2013 5:23 AM
    Sunday, October 13, 2013 5:05 PM

All replies

  • See if my post at http://www.thinqlinq.com/Post.aspx/Title/Revising-the-Reactive-Sensor-Generator.aspx helps.

    http://www.ThinqLinq.com http://www.LinqInAction.net - "LINQ In Action", The book is now available. Don't wait for the movie

    Sunday, October 13, 2013 3:40 PM
  • Hi,

    > I would like to introduce some randomness and generate it more like [snip]

    Your usage of Generate is fine, though it's a bad idea to create a new Random instance each iteration, even though in your particular usage it won't matter because of how long you're waiting between notifications.  Instead, you should create one instance of Random outside of the query and then use it within the query.

    That's unrelated to your stated problem though.

    > I suscpect I would need to Subscribe to the stream, but then I'm unable to form the following query, which should consume the data [snip]

    Generate returns a cold observable, so you must either subscribe to it directly or use it within another query, as you are doing.

    See my blog post on Hot and Cold Observables for details.

    However, I suspect that the reason you think that it's not working is simply because you expect that Generate will push the first notification immediately, though in fact it does not.  It applies the specified delay to the first element, just as is does for every other element.

    To ensure that _dataSource pushes an element immediately when an observer subscribes, either apply the StartWith operator or add a conditional to your interval algorithm.

    Here's an example of the latter:

    i => i == 0 ? TimeSpan.Zero : TimeSpan.FromSeconds(random.Next(300, 2000))

    - Dave


    http://davesexton.com/blog

    • Marked as answer by Veksi Thursday, October 17, 2013 5:23 AM
    Sunday, October 13, 2013 5:05 PM