1

I have a while loop that runs for a long number of times. I have some writelines in there that serve as debug statements. I use a verbosity flag to determine when I want to see those statements written to the console. Is there a way I can also specify to output every x milliseconds , instead of all the time.

while
{
   //logic here
   if(verboseMode)
       Console.Writeline("some status message")
}

With the way the code is right now, the writeline executes all the time when verboseMode is set to true. What id like to do is output the line if verboseMode is set to true and the last time I output something it was x milliseconds ago

huysentruitw
  • 27,376
  • 9
  • 90
  • 133
rustyocean
  • 233
  • 5
  • 14
  • [Timer class](https://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx?cs-save-lang=1&cs-lang=csharp) would be useful probably – abney317 Feb 09 '18 at 17:40
  • remeber when you output something, check on output if time elapsed is ok, if so print, if not, print not? – Patrick Artner Feb 09 '18 at 17:43

3 Answers3

0

What you ask for is rate limiting. I wrote this code originally for Multithreading, but it should get you the idea:

integer interval = 20;
DateTime dueTime = DateTime.Now.AddMillisconds(interval);

while(true){
  if(DateTime.Now >= dueTime){
    //insert code here

    //Update next dueTime
    dueTime = DateTime.Now.AddMillisconds(interval);
  }
  else{
    //Just yield to not tax out the CPU
    Thread.Sleep(1);
  }
}

Note that DateTime is not nearly as accurate as the type is precise. Often the smalest difference tracked is 16 ms or so. But then again, 16 ms would get you around 60 changes per seconds, wich is propably to top adivseable writing/updating speed anyway.

Christopher
  • 9,634
  • 2
  • 17
  • 31
0

You can use a Timer or just keep track of when you last wrote output. The Timer is probably preferable because your main functionality won't block it from running whereas the other will.

I used random just to simulate the fact that the while loop won't always run in the same amount of time to demonstrate the difference between the approaches.

var r = new Random();
var t = new System.Timers.Timer() { Interval = 1500 };
t.Elapsed += (s, e) =>
    Console.WriteLine(DateTime.Now.TimeOfDay);
t.Start();
while (true)
{
    Thread.Sleep(r.Next(500, 1000));
    Console.WriteLine("doing stuff");
}

var r = new Random();
var prev = DateTime.Now;
var interval = 1500;
while (true)
{
    Thread.Sleep(r.Next(500, 1000));
    Console.WriteLine("doing stuff");
    var now = DateTime.Now;
    if (prev.AddMilliseconds(interval) >= now)
    {
        prev = DateTime.Now;
        Console.WriteLine(DateTime.Now.TimeOfDay);
    }
}
Blake Thingstad
  • 1,639
  • 2
  • 12
  • 19
0

If you don't care much about precision you can get away with running the while loop on a different thread using Task.Run:

var source = new CancellationTokenSource();

var task = Task.Run(() => 
{
    while (!source.Token.IsCancellationRequested)
    {
        DoSomething();
        await Task.Delay(500, source.Token);
    }
});

// If you want to cancel the loop
source.Cancel();
task.Wait(); // or 'await task;' if you're in an async method
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
  • https://stackoverflow.com/questions/32726294/is-async-await-using-task-run-starting-a-new-thread-asynchronously – Rand Random Feb 09 '18 at 18:10
  • You are saying `while loop on a different thread using Task.Run` - a Task.Run wont always be in a different thread. – Rand Random Feb 09 '18 at 18:13
  • The calling code will certainly not wait for anything (unless you call `await task`). And the only way to do that on any OS is running the code on a different thread. – huysentruitw Feb 09 '18 at 18:14