5

Observable.Interval produces value every period of time. How to make it wait until action ends before the next iteration?

Example:

Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(async t => 
{
    //Here could be some long running action with different duration each iteration
    Console.WriteLine(t.ToString());
    await Task.Delay(3000);
});

It will start action every second. How to make it wait until action is completed?

2 Answers2

0

What you're asking for is the default behaviour - unless you introduce async/await - so remove the async and use Task.Delay(3000).Wait() instead.

Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(t => 
{
    //Here could be some long running action with different duration each iteration
    Console.WriteLine(t.ToString());
    Task.Delay(3000).Wait();
});

The contract for observables will only produce a new value once the observers are done - unless you introduce async.

Observable.Interval(TimeSpan.FromSeconds(1)) doesn't produce a value every second - it produces an interval of one second between the observer(s) finishing and the next one starting.

So, if you have a long running observer you'll still have a full second between one finishing and next starting.

Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • Sorry, but it does not work as expected `code` Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(t => { //Here could be some long running action with different duration each iteration Console.WriteLine("Before " + DateTime.Now.ToLongTimeString().ToString()); Task.Delay(3000).Wait(); Console.WriteLine("After " + DateTime.Now.ToLongTimeString().ToString()); }); `code` Last "After" with next "Before" won`t have 1 seconds interval. – JiZhaku_San Oct 12 '16 at 13:06
  • Sorry, but it does not work as expected code `Observable.Interval(TimeSpan.FromSeconds(1)).Subscribe(t => { Console.WriteLine("Before " + DateTime.Now.ToLongTimeString().ToString()); Task.Delay(3000).Wait(); Console.WriteLine("After " + DateTime.Now.ToLongTimeString().ToString()); });` Last "After" with next "Before" won`t have 1 seconds interval. – JiZhaku_San Oct 12 '16 at 13:09
-1

Why not implement it yourself? Use TaskFactory.StartNew in a while loop or recursive method. Then simulate work by using Task.Delay

Juan Carlos
  • 490
  • 5
  • 17
  • Actually I want to avoid using while loop or recursive methods. – JiZhaku_San Oct 12 '16 at 11:06
  • You can do something similar you know. But without passing the timespan, you can implement something that ask for action, and what you do is get that action, make it a task, and when that task completes call the action again. Check this post: http://stackoverflow.com/questions/13695499/proper-way-to-implement-a-never-ending-task-timers-vs-task – Juan Carlos Oct 12 '16 at 11:35